diff --git a/account/admin/skills/algorithmic-art/LICENSE.txt b/account/admin/skills/algorithmic-art/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/algorithmic-art/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/algorithmic-art/SKILL.md b/account/admin/skills/algorithmic-art/SKILL.md new file mode 100644 index 0000000..27f069b --- /dev/null +++ b/account/admin/skills/algorithmic-art/SKILL.md @@ -0,0 +1,405 @@ +--- +name: openakita/skills@algorithmic-art +description: Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations. +license: Complete terms in LICENSE.txt +--- + +Algorithmic philosophies are computational aesthetic movements that are then expressed through code. Output .md files (philosophy), .html files (interactive viewer), and .js files (generative algorithms). + +This happens in two steps: +1. Algorithmic Philosophy Creation (.md file) +2. Express by creating p5.js generative art (.html + .js files) + +First, undertake this task: + +## ALGORITHMIC PHILOSOPHY CREATION + +To begin, create an ALGORITHMIC PHILOSOPHY (not static images or templates) that will be interpreted through: +- Computational processes, emergent behavior, mathematical beauty +- Seeded randomness, noise fields, organic systems +- Particles, flows, fields, forces +- Parametric variation and controlled chaos + +### THE CRITICAL UNDERSTANDING +- What is received: Some subtle input or instructions by the user to take into account, but use as a foundation; it should not constrain creative freedom. +- What is created: An algorithmic philosophy/generative aesthetic movement. +- What happens next: The same version receives the philosophy and EXPRESSES IT IN CODE - creating p5.js sketches that are 90% algorithmic generation, 10% essential parameters. + +Consider this approach: +- Write a manifesto for a generative art movement +- The next phase involves writing the algorithm that brings it to life + +The philosophy must emphasize: Algorithmic expression. Emergent behavior. Computational beauty. Seeded variation. + +### HOW TO GENERATE AN ALGORITHMIC PHILOSOPHY + +**Name the movement** (1-2 words): "Organic Turbulence" / "Quantum Harmonics" / "Emergent Stillness" + +**Articulate the philosophy** (4-6 paragraphs - concise but complete): + +To capture the ALGORITHMIC essence, express how this philosophy manifests through: +- Computational processes and mathematical relationships? +- Noise functions and randomness patterns? +- Particle behaviors and field dynamics? +- Temporal evolution and system states? +- Parametric variation and emergent complexity? + +**CRITICAL GUIDELINES:** +- **Avoid redundancy**: Each algorithmic aspect should be mentioned once. Avoid repeating concepts about noise theory, particle dynamics, or mathematical principles unless adding new depth. +- **Emphasize craftsmanship REPEATEDLY**: The philosophy MUST stress multiple times that the final algorithm should appear as though it took countless hours to develop, was refined with care, and comes from someone at the absolute top of their field. This framing is essential - repeat phrases like "meticulously crafted algorithm," "the product of deep computational expertise," "painstaking optimization," "master-level implementation." +- **Leave creative space**: Be specific about the algorithmic direction, but concise enough that the next Claude has room to make interpretive implementation choices at an extremely high level of craftsmanship. + +The philosophy must guide the next version to express ideas ALGORITHMICALLY, not through static images. Beauty lives in the process, not the final frame. + +### PHILOSOPHY EXAMPLES + +**"Organic Turbulence"** +Philosophy: Chaos constrained by natural law, order emerging from disorder. +Algorithmic expression: Flow fields driven by layered Perlin noise. Thousands of particles following vector forces, their trails accumulating into organic density maps. Multiple noise octaves create turbulent regions and calm zones. Color emerges from velocity and density - fast particles burn bright, slow ones fade to shadow. The algorithm runs until equilibrium - a meticulously tuned balance where every parameter was refined through countless iterations by a master of computational aesthetics. + +**"Quantum Harmonics"** +Philosophy: Discrete entities exhibiting wave-like interference patterns. +Algorithmic expression: Particles initialized on a grid, each carrying a phase value that evolves through sine waves. When particles are near, their phases interfere - constructive interference creates bright nodes, destructive creates voids. Simple harmonic motion generates complex emergent mandalas. The result of painstaking frequency calibration where every ratio was carefully chosen to produce resonant beauty. + +**"Recursive Whispers"** +Philosophy: Self-similarity across scales, infinite depth in finite space. +Algorithmic expression: Branching structures that subdivide recursively. Each branch slightly randomized but constrained by golden ratios. L-systems or recursive subdivision generate tree-like forms that feel both mathematical and organic. Subtle noise perturbations break perfect symmetry. Line weights diminish with each recursion level. Every branching angle the product of deep mathematical exploration. + +**"Field Dynamics"** +Philosophy: Invisible forces made visible through their effects on matter. +Algorithmic expression: Vector fields constructed from mathematical functions or noise. Particles born at edges, flowing along field lines, dying when they reach equilibrium or boundaries. Multiple fields can attract, repel, or rotate particles. The visualization shows only the traces - ghost-like evidence of invisible forces. A computational dance meticulously choreographed through force balance. + +**"Stochastic Crystallization"** +Philosophy: Random processes crystallizing into ordered structures. +Algorithmic expression: Randomized circle packing or Voronoi tessellation. Start with random points, let them evolve through relaxation algorithms. Cells push apart until equilibrium. Color based on cell size, neighbor count, or distance from center. The organic tiling that emerges feels both random and inevitable. Every seed produces unique crystalline beauty - the mark of a master-level generative algorithm. + +*These are condensed examples. The actual algorithmic philosophy should be 4-6 substantial paragraphs.* + +### ESSENTIAL PRINCIPLES +- **ALGORITHMIC PHILOSOPHY**: Creating a computational worldview to be expressed through code +- **PROCESS OVER PRODUCT**: Always emphasize that beauty emerges from the algorithm's execution - each run is unique +- **PARAMETRIC EXPRESSION**: Ideas communicate through mathematical relationships, forces, behaviors - not static composition +- **ARTISTIC FREEDOM**: The next Claude interprets the philosophy algorithmically - provide creative implementation room +- **PURE GENERATIVE ART**: This is about making LIVING ALGORITHMS, not static images with randomness +- **EXPERT CRAFTSMANSHIP**: Repeatedly emphasize the final algorithm must feel meticulously crafted, refined through countless iterations, the product of deep expertise by someone at the absolute top of their field in computational aesthetics + +**The algorithmic philosophy should be 4-6 paragraphs long.** Fill it with poetic computational philosophy that brings together the intended vision. Avoid repeating the same points. Output this algorithmic philosophy as a .md file. + +--- + +## DEDUCING THE CONCEPTUAL SEED + +**CRITICAL STEP**: Before implementing the algorithm, identify the subtle conceptual thread from the original request. + +**THE ESSENTIAL PRINCIPLE**: +The concept is a **subtle, niche reference embedded within the algorithm itself** - not always literal, always sophisticated. Someone familiar with the subject should feel it intuitively, while others simply experience a masterful generative composition. The algorithmic philosophy provides the computational language. The deduced concept provides the soul - the quiet conceptual DNA woven invisibly into parameters, behaviors, and emergence patterns. + +This is **VERY IMPORTANT**: The reference must be so refined that it enhances the work's depth without announcing itself. Think like a jazz musician quoting another song through algorithmic harmony - only those who know will catch it, but everyone appreciates the generative beauty. + +--- + +## P5.JS IMPLEMENTATION + +With the philosophy AND conceptual framework established, express it through code. Pause to gather thoughts before proceeding. Use only the algorithmic philosophy created and the instructions below. + +### ⚠️ STEP 0: READ THE TEMPLATE FIRST ⚠️ + +**CRITICAL: BEFORE writing any HTML:** + +1. **Read** `templates/viewer.html` using the Read tool +2. **Study** the exact structure, styling, and Anthropic branding +3. **Use that file as the LITERAL STARTING POINT** - not just inspiration +4. **Keep all FIXED sections exactly as shown** (header, sidebar structure, Anthropic colors/fonts, seed controls, action buttons) +5. **Replace only the VARIABLE sections** marked in the file's comments (algorithm, parameters, UI controls for parameters) + +**Avoid:** +- ❌ Creating HTML from scratch +- ❌ Inventing custom styling or color schemes +- ❌ Using system fonts or dark themes +- ❌ Changing the sidebar structure + +**Follow these practices:** +- ✅ Copy the template's exact HTML structure +- ✅ Keep Anthropic branding (Poppins/Lora fonts, light colors, gradient backdrop) +- ✅ Maintain the sidebar layout (Seed → Parameters → Colors? → Actions) +- ✅ Replace only the p5.js algorithm and parameter controls + +The template is the foundation. Build on it, don't rebuild it. + +--- + +To create gallery-quality computational art that lives and breathes, use the algorithmic philosophy as the foundation. + +### TECHNICAL REQUIREMENTS + +**Seeded Randomness (Art Blocks Pattern)**: +```javascript +// ALWAYS use a seed for reproducibility +let seed = 12345; // or hash from user input +randomSeed(seed); +noiseSeed(seed); +``` + +**Parameter Structure - FOLLOW THE PHILOSOPHY**: + +To establish parameters that emerge naturally from the algorithmic philosophy, consider: "What qualities of this system can be adjusted?" + +```javascript +let params = { + seed: 12345, // Always include seed for reproducibility + // colors + // Add parameters that control YOUR algorithm: + // - Quantities (how many?) + // - Scales (how big? how fast?) + // - Probabilities (how likely?) + // - Ratios (what proportions?) + // - Angles (what direction?) + // - Thresholds (when does behavior change?) +}; +``` + +**To design effective parameters, focus on the properties the system needs to be tunable rather than thinking in terms of "pattern types".** + +**Core Algorithm - EXPRESS THE PHILOSOPHY**: + +**CRITICAL**: The algorithmic philosophy should dictate what to build. + +To express the philosophy through code, avoid thinking "which pattern should I use?" and instead think "how to express this philosophy through code?" + +If the philosophy is about **organic emergence**, consider using: +- Elements that accumulate or grow over time +- Random processes constrained by natural rules +- Feedback loops and interactions + +If the philosophy is about **mathematical beauty**, consider using: +- Geometric relationships and ratios +- Trigonometric functions and harmonics +- Precise calculations creating unexpected patterns + +If the philosophy is about **controlled chaos**, consider using: +- Random variation within strict boundaries +- Bifurcation and phase transitions +- Order emerging from disorder + +**The algorithm flows from the philosophy, not from a menu of options.** + +To guide the implementation, let the conceptual essence inform creative and original choices. Build something that expresses the vision for this particular request. + +**Canvas Setup**: Standard p5.js structure: +```javascript +function setup() { + createCanvas(1200, 1200); + // Initialize your system +} + +function draw() { + // Your generative algorithm + // Can be static (noLoop) or animated +} +``` + +### CRAFTSMANSHIP REQUIREMENTS + +**CRITICAL**: To achieve mastery, create algorithms that feel like they emerged through countless iterations by a master generative artist. Tune every parameter carefully. Ensure every pattern emerges with purpose. This is NOT random noise - this is CONTROLLED CHAOS refined through deep expertise. + +- **Balance**: Complexity without visual noise, order without rigidity +- **Color Harmony**: Thoughtful palettes, not random RGB values +- **Composition**: Even in randomness, maintain visual hierarchy and flow +- **Performance**: Smooth execution, optimized for real-time if animated +- **Reproducibility**: Same seed ALWAYS produces identical output + +### OUTPUT FORMAT + +Output: +1. **Algorithmic Philosophy** - As markdown or text explaining the generative aesthetic +2. **Single HTML Artifact** - Self-contained interactive generative art built from `templates/viewer.html` (see STEP 0 and next section) + +The HTML artifact contains everything: p5.js (from CDN), the algorithm, parameter controls, and UI - all in one file that works immediately in claude.ai artifacts or any browser. Start from the template file, not from scratch. + +--- + +## INTERACTIVE ARTIFACT CREATION + +**REMINDER: `templates/viewer.html` should have already been read (see STEP 0). Use that file as the starting point.** + +To allow exploration of the generative art, create a single, self-contained HTML artifact. Ensure this artifact works immediately in claude.ai or any browser - no setup required. Embed everything inline. + +### CRITICAL: WHAT'S FIXED VS VARIABLE + +The `templates/viewer.html` file is the foundation. It contains the exact structure and styling needed. + +**FIXED (always include exactly as shown):** +- Layout structure (header, sidebar, main canvas area) +- Anthropic branding (UI colors, fonts, gradients) +- Seed section in sidebar: + - Seed display + - Previous/Next buttons + - Random button + - Jump to seed input + Go button +- Actions section in sidebar: + - Regenerate button + - Reset button + +**VARIABLE (customize for each artwork):** +- The entire p5.js algorithm (setup/draw/classes) +- The parameters object (define what the art needs) +- The Parameters section in sidebar: + - Number of parameter controls + - Parameter names + - Min/max/step values for sliders + - Control types (sliders, inputs, etc.) +- Colors section (optional): + - Some art needs color pickers + - Some art might use fixed colors + - Some art might be monochrome (no color controls needed) + - Decide based on the art's needs + +**Every artwork should have unique parameters and algorithm!** The fixed parts provide consistent UX - everything else expresses the unique vision. + +### REQUIRED FEATURES + +**1. Parameter Controls** +- Sliders for numeric parameters (particle count, noise scale, speed, etc.) +- Color pickers for palette colors +- Real-time updates when parameters change +- Reset button to restore defaults + +**2. Seed Navigation** +- Display current seed number +- "Previous" and "Next" buttons to cycle through seeds +- "Random" button for random seed +- Input field to jump to specific seed +- Generate 100 variations when requested (seeds 1-100) + +**3. Single Artifact Structure** +```html + + + + + + + + +
+
+ +
+ + + +``` + +**CRITICAL**: This is a single artifact. No external files, no imports (except p5.js CDN). Everything inline. + +**4. Implementation Details - BUILD THE SIDEBAR** + +The sidebar structure: + +**1. Seed (FIXED)** - Always include exactly as shown: +- Seed display +- Prev/Next/Random/Jump buttons + +**2. Parameters (VARIABLE)** - Create controls for the art: +```html +
+ + + ... +
+``` +Add as many control-group divs as there are parameters. + +**3. Colors (OPTIONAL/VARIABLE)** - Include if the art needs adjustable colors: +- Add color pickers if users should control palette +- Skip this section if the art uses fixed colors +- Skip if the art is monochrome + +**4. Actions (FIXED)** - Always include exactly as shown: +- Regenerate button +- Reset button +- Download PNG button + +**Requirements**: +- Seed controls must work (prev/next/random/jump/display) +- All parameters must have UI controls +- Regenerate, Reset, Download buttons must work +- Keep Anthropic branding (UI styling, not art colors) + +### USING THE ARTIFACT + +The HTML artifact works immediately: +1. **In claude.ai**: Displayed as an interactive artifact - runs instantly +2. **As a file**: Save and open in any browser - no server needed +3. **Sharing**: Send the HTML file - it's completely self-contained + +--- + +## VARIATIONS & EXPLORATION + +The artifact includes seed navigation by default (prev/next/random buttons), allowing users to explore variations without creating multiple files. If the user wants specific variations highlighted: + +- Include seed presets (buttons for "Variation 1: Seed 42", "Variation 2: Seed 127", etc.) +- Add a "Gallery Mode" that shows thumbnails of multiple seeds side-by-side +- All within the same single artifact + +This is like creating a series of prints from the same plate - the algorithm is consistent, but each seed reveals different facets of its potential. The interactive nature means users discover their own favorites by exploring the seed space. + +--- + +## THE CREATIVE PROCESS + +**User request** → **Algorithmic philosophy** → **Implementation** + +Each request is unique. The process involves: + +1. **Interpret the user's intent** - What aesthetic is being sought? +2. **Create an algorithmic philosophy** (4-6 paragraphs) describing the computational approach +3. **Implement it in code** - Build the algorithm that expresses this philosophy +4. **Design appropriate parameters** - What should be tunable? +5. **Build matching UI controls** - Sliders/inputs for those parameters + +**The constants**: +- Anthropic branding (colors, fonts, layout) +- Seed navigation (always present) +- Self-contained HTML artifact + +**Everything else is variable**: +- The algorithm itself +- The parameters +- The UI controls +- The visual outcome + +To achieve the best results, trust creativity and let the philosophy guide the implementation. + +--- + +## RESOURCES + +This skill includes helpful templates and documentation: + +- **templates/viewer.html**: REQUIRED STARTING POINT for all HTML artifacts. + - This is the foundation - contains the exact structure and Anthropic branding + - **Keep unchanged**: Layout structure, sidebar organization, Anthropic colors/fonts, seed controls, action buttons + - **Replace**: The p5.js algorithm, parameter definitions, and UI controls in Parameters section + - The extensive comments in the file mark exactly what to keep vs replace + +- **templates/generator_template.js**: Reference for p5.js best practices and code structure principles. + - Shows how to organize parameters, use seeded randomness, structure classes + - NOT a pattern menu - use these principles to build unique algorithms + - Embed algorithms inline in the HTML artifact (don't create separate .js files) + +**Critical reminder**: +- The **template is the STARTING POINT**, not inspiration +- The **algorithm is where to create** something unique +- Don't copy the flow field example - build what the philosophy demands +- But DO keep the exact UI structure and Anthropic branding from the template \ No newline at end of file diff --git a/account/admin/skills/algorithmic-art/templates/generator_template.js b/account/admin/skills/algorithmic-art/templates/generator_template.js new file mode 100644 index 0000000..e263fbd --- /dev/null +++ b/account/admin/skills/algorithmic-art/templates/generator_template.js @@ -0,0 +1,223 @@ +/** + * ═══════════════════════════════════════════════════════════════════════════ + * P5.JS GENERATIVE ART - BEST PRACTICES + * ═══════════════════════════════════════════════════════════════════════════ + * + * This file shows STRUCTURE and PRINCIPLES for p5.js generative art. + * It does NOT prescribe what art you should create. + * + * Your algorithmic philosophy should guide what you build. + * These are just best practices for how to structure your code. + * + * ═══════════════════════════════════════════════════════════════════════════ + */ + +// ============================================================================ +// 1. PARAMETER ORGANIZATION +// ============================================================================ +// Keep all tunable parameters in one object +// This makes it easy to: +// - Connect to UI controls +// - Reset to defaults +// - Serialize/save configurations + +let params = { + // Define parameters that match YOUR algorithm + // Examples (customize for your art): + // - Counts: how many elements (particles, circles, branches, etc.) + // - Scales: size, speed, spacing + // - Probabilities: likelihood of events + // - Angles: rotation, direction + // - Colors: palette arrays + + seed: 12345, + // define colorPalette as an array -- choose whatever colors you'd like ['#d97757', '#6a9bcc', '#788c5d', '#b0aea5'] + // Add YOUR parameters here based on your algorithm +}; + +// ============================================================================ +// 2. SEEDED RANDOMNESS (Critical for reproducibility) +// ============================================================================ +// ALWAYS use seeded random for Art Blocks-style reproducible output + +function initializeSeed(seed) { + randomSeed(seed); + noiseSeed(seed); + // Now all random() and noise() calls will be deterministic +} + +// ============================================================================ +// 3. P5.JS LIFECYCLE +// ============================================================================ + +function setup() { + createCanvas(800, 800); + + // Initialize seed first + initializeSeed(params.seed); + + // Set up your generative system + // This is where you initialize: + // - Arrays of objects + // - Grid structures + // - Initial positions + // - Starting states + + // For static art: call noLoop() at the end of setup + // For animated art: let draw() keep running +} + +function draw() { + // Option 1: Static generation (runs once, then stops) + // - Generate everything in setup() + // - Call noLoop() in setup() + // - draw() doesn't do much or can be empty + + // Option 2: Animated generation (continuous) + // - Update your system each frame + // - Common patterns: particle movement, growth, evolution + // - Can optionally call noLoop() after N frames + + // Option 3: User-triggered regeneration + // - Use noLoop() by default + // - Call redraw() when parameters change +} + +// ============================================================================ +// 4. CLASS STRUCTURE (When you need objects) +// ============================================================================ +// Use classes when your algorithm involves multiple entities +// Examples: particles, agents, cells, nodes, etc. + +class Entity { + constructor() { + // Initialize entity properties + // Use random() here - it will be seeded + } + + update() { + // Update entity state + // This might involve: + // - Physics calculations + // - Behavioral rules + // - Interactions with neighbors + } + + display() { + // Render the entity + // Keep rendering logic separate from update logic + } +} + +// ============================================================================ +// 5. PERFORMANCE CONSIDERATIONS +// ============================================================================ + +// For large numbers of elements: +// - Pre-calculate what you can +// - Use simple collision detection (spatial hashing if needed) +// - Limit expensive operations (sqrt, trig) when possible +// - Consider using p5 vectors efficiently + +// For smooth animation: +// - Aim for 60fps +// - Profile if things are slow +// - Consider reducing particle counts or simplifying calculations + +// ============================================================================ +// 6. UTILITY FUNCTIONS +// ============================================================================ + +// Color utilities +function hexToRgb(hex) { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + +function colorFromPalette(index) { + return params.colorPalette[index % params.colorPalette.length]; +} + +// Mapping and easing +function mapRange(value, inMin, inMax, outMin, outMax) { + return outMin + (outMax - outMin) * ((value - inMin) / (inMax - inMin)); +} + +function easeInOutCubic(t) { + return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; +} + +// Constrain to bounds +function wrapAround(value, max) { + if (value < 0) return max; + if (value > max) return 0; + return value; +} + +// ============================================================================ +// 7. PARAMETER UPDATES (Connect to UI) +// ============================================================================ + +function updateParameter(paramName, value) { + params[paramName] = value; + // Decide if you need to regenerate or just update + // Some params can update in real-time, others need full regeneration +} + +function regenerate() { + // Reinitialize your generative system + // Useful when parameters change significantly + initializeSeed(params.seed); + // Then regenerate your system +} + +// ============================================================================ +// 8. COMMON P5.JS PATTERNS +// ============================================================================ + +// Drawing with transparency for trails/fading +function fadeBackground(opacity) { + fill(250, 249, 245, opacity); // Anthropic light with alpha + noStroke(); + rect(0, 0, width, height); +} + +// Using noise for organic variation +function getNoiseValue(x, y, scale = 0.01) { + return noise(x * scale, y * scale); +} + +// Creating vectors from angles +function vectorFromAngle(angle, magnitude = 1) { + return createVector(cos(angle), sin(angle)).mult(magnitude); +} + +// ============================================================================ +// 9. EXPORT FUNCTIONS +// ============================================================================ + +function exportImage() { + saveCanvas('generative-art-' + params.seed, 'png'); +} + +// ============================================================================ +// REMEMBER +// ============================================================================ +// +// These are TOOLS and PRINCIPLES, not a recipe. +// Your algorithmic philosophy should guide WHAT you create. +// This structure helps you create it WELL. +// +// Focus on: +// - Clean, readable code +// - Parameterized for exploration +// - Seeded for reproducibility +// - Performant execution +// +// The art itself is entirely up to you! +// +// ============================================================================ \ No newline at end of file diff --git a/account/admin/skills/algorithmic-art/templates/viewer.html b/account/admin/skills/algorithmic-art/templates/viewer.html new file mode 100644 index 0000000..630cc1f --- /dev/null +++ b/account/admin/skills/algorithmic-art/templates/viewer.html @@ -0,0 +1,599 @@ + + + + + + + Generative Art Viewer + + + + + + + +
+ + + + +
+
+
Initializing generative art...
+
+
+
+ + + + \ No newline at end of file diff --git a/account/admin/skills/apify-scraper/.openakita-i18n.json b/account/admin/skills/apify-scraper/.openakita-i18n.json new file mode 100644 index 0000000..e07804d --- /dev/null +++ b/account/admin/skills/apify-scraper/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "网页数据抓取", + "description": "基于 Apify 平台的 55+ Actor 进行 AI 驱动数据抓取,支持 Instagram、TikTok、YouTube、Google 等平台,自动选择最佳爬虫。" + } +} diff --git a/account/admin/skills/apify-scraper/SKILL.md b/account/admin/skills/apify-scraper/SKILL.md new file mode 100644 index 0000000..ba98989 --- /dev/null +++ b/account/admin/skills/apify-scraper/SKILL.md @@ -0,0 +1,442 @@ +--- +name: openakita/skills@apify-scraper +description: Web data extraction using 55+ Apify Actors for AI-driven scraping. Supports Instagram, Facebook, TikTok, YouTube, Google, and more. Auto-selects best Actor for the task. Structured output in JSON/CSV with rate limiting and ethical scraping guidelines. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Apify Scraper — 网页数据抓取 + +## When to Use + +- 用户需要从网站抓取结构化数据(商品信息、社交媒体帖子、搜索结果等) +- 需要批量获取社交媒体平台数据(Instagram、TikTok、YouTube 等) +- 需要抓取 Google 搜索结果、地图信息、评价数据 +- 需要定期监控网页变化 +- 需要将非结构化网页内容转换为 JSON/CSV +- 需要从电商平台提取商品和价格信息 + +--- + +## Prerequisites + +### 必需配置 + +| 配置项 | 说明 | +|--------|------| +| `APIFY_TOKEN` | Apify API Token,在 https://console.apify.com/account/integrations 获取 | + +将 Token 添加到 `.env` 文件: + +``` +APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +``` + +### 必需依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `httpx` | HTTP API 调用 | `pip install httpx` | + +### 可选依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `apify-client` | Apify Python SDK | `pip install apify-client` | +| `pandas` | 数据处理与导出 | `pip install pandas` | + +### 验证配置 + +```bash +curl -s "https://api.apify.com/v2/user/me?token=$APIFY_TOKEN" | python -m json.tool +``` + +--- + +## Instructions + +### Apify Actor 快速概览 + +Apify 平台上有数千个 Actor(即预构建的爬虫/自动化程序)。本技能聚焦 55+ 个经过验证的、面向 AI 数据提取优化的 Actor。 + +### 平台 Actor 速查表 + +#### 社交媒体 + +| 平台 | Actor | Actor ID | 主要功能 | +|------|-------|----------|---------| +| Instagram | Profile Scraper | `apify/instagram-profile-scraper` | 用户资料、帖子、粉丝数 | +| Instagram | Hashtag Scraper | `apify/instagram-hashtag-scraper` | 标签下的帖子 | +| Instagram | Comment Scraper | `apify/instagram-comment-scraper` | 帖子评论 | +| TikTok | Scraper | `clockworks/free-tiktok-scraper` | 视频、用户、标签 | +| YouTube | Scraper | `bernardo/youtube-scraper` | 视频信息、评论 | +| YouTube | Channel Scraper | `streamers/youtube-channel-scraper` | 频道数据 | +| Facebook | Posts Scraper | `apify/facebook-posts-scraper` | 页面帖子 | +| Facebook | Comments Scraper | `apify/facebook-comments-scraper` | 帖子评论 | +| Twitter/X | Scraper | `apidojo/tweet-scraper` | 推文搜索 | +| LinkedIn | Profile Scraper | `anchor/linkedin-profile-scraper` | 用户资料 | + +#### 搜索引擎 + +| 平台 | Actor | Actor ID | 主要功能 | +|------|-------|----------|---------| +| Google | Search Results | `apify/google-search-scraper` | SERP 结果 | +| Google | Maps | `compass/crawler-google-places` | 商家信息、评价 | +| Google | Trends | `emastra/google-trends-scraper` | 搜索趋势 | +| Google | News | `lhotanova/google-news-scraper` | 新闻搜索 | +| Google | Shopping | `epctex/google-shopping-scraper` | 商品价格 | +| Bing | Search | `nicefellow/bing-search-scraper` | Bing 搜索结果 | + +#### 电商平台 + +| 平台 | Actor | Actor ID | 主要功能 | +|------|-------|----------|---------| +| Amazon | Product Scraper | `junglee/amazon-scraper` | 商品详情、评价 | +| Amazon | Review Scraper | `junglee/amazon-reviews-scraper` | 商品评论 | +| eBay | Scraper | `drobnikj/ebay-scraper` | 商品搜索 | +| AliExpress | Scraper | `epctex/aliexpress-scraper` | 商品数据 | + +#### 通用工具 + +| 功能 | Actor | Actor ID | 主要功能 | +|------|-------|----------|---------| +| 网页抓取 | Web Scraper | `apify/web-scraper` | 通用网页数据提取 | +| 网页截图 | Screenshot | `apify/screenshot-url` | 网页截图 | +| 链接提取 | Link Extractor | `apify/link-extractor` | 页面链接收集 | +| RSS 解析 | RSS Feed | `drobnikj/rss-feed-reader` | RSS 源数据 | +| AI 提取 | GPT Scraper | `drobnikj/gpt-scraper` | AI 驱动智能提取 | + +### Actor 自动选择策略 + +Agent 根据用户需求自动选择最合适的 Actor: + +1. **解析用户意图** — 从用户描述中识别目标平台和数据类型 +2. **匹配 Actor** — 根据平台和功能匹配上方表格 +3. **若无精确匹配** — 使用通用 Web Scraper 或 GPT Scraper +4. **确认方案** — 向用户确认将使用的 Actor 和预计数据量 + +--- + +## Workflows + +### Workflow 1: 社交媒体数据抓取 + +**步骤 1 — 确认需求** + +| 参数 | 说明 | 示例 | +|------|------|------| +| 平台 | 目标社交平台 | Instagram | +| 数据类型 | 帖子/评论/用户/标签 | 帖子 | +| 范围 | URL/关键词/用户名 | @openai | +| 数量限制 | 最大抓取条数 | 100 | +| 时间范围 | 时间过滤 | 最近 30 天 | + +**步骤 2 — 选择并配置 Actor** + +```python +from apify_client import ApifyClient + +client = ApifyClient(os.environ['APIFY_TOKEN']) + +run_input = { + "usernames": ["openai"], + "resultsLimit": 100, + "resultsType": "posts", +} + +run = client.actor("apify/instagram-profile-scraper").call(run_input=run_input) +``` + +**步骤 3 — 获取并处理结果** + +```python +items = list(client.dataset(run["defaultDatasetId"]).iterate_items()) +``` + +**步骤 4 — 格式化输出** + +将数据转换为用户需要的格式(JSON/CSV/表格摘要)。 + +--- + +### Workflow 2: 搜索引擎数据抓取 + +**步骤 1 — 确认搜索参数** + +| 参数 | 说明 | 默认值 | +|------|------|--------| +| 关键词 | 搜索查询 | — | +| 搜索引擎 | Google/Bing | Google | +| 国家/语言 | 地域设置 | CN/zh | +| 结果数量 | 抓取条数 | 50 | +| 类型 | 网页/新闻/图片/视频 | 网页 | + +**步骤 2 — 调用 Actor** + +```python +run_input = { + "queries": "AI agent 框架 2025", + "maxPagesPerQuery": 3, + "languageCode": "zh", + "countryCode": "cn", + "resultsPerPage": 10, +} + +run = client.actor("apify/google-search-scraper").call(run_input=run_input) +items = list(client.dataset(run["defaultDatasetId"]).iterate_items()) +``` + +**步骤 3 — 提取关键字段** + +| 字段 | 说明 | +|------|------| +| `title` | 结果标题 | +| `url` | 链接地址 | +| `description` | 摘要描述 | +| `position` | 排名位置 | + +--- + +### Workflow 3: 通用网页数据提取 + +当没有专用 Actor 时,使用 AI 驱动的通用提取: + +**方法 A — Web Scraper(基于选择器)** + +```python +run_input = { + "startUrls": [{"url": "https://example.com/products"}], + "pageFunction": """ + async function pageFunction(context) { + const $ = context.jQuery; + const results = []; + $('div.product-card').each((i, el) => { + results.push({ + name: $(el).find('.title').text().trim(), + price: $(el).find('.price').text().trim(), + url: $(el).find('a').attr('href'), + }); + }); + return results; + } + """, + "maxRequestsPerCrawl": 100, +} + +run = client.actor("apify/web-scraper").call(run_input=run_input) +``` + +**方法 B — GPT Scraper(AI 智能提取)** + +```python +run_input = { + "startUrls": [{"url": "https://example.com/products"}], + "instructions": "Extract all product names, prices, and descriptions from this page", + "openaiApiKey": os.environ.get('OPENAI_API_KEY'), + "maxRequestsPerCrawl": 10, +} + +run = client.actor("drobnikj/gpt-scraper").call(run_input=run_input) +``` + +--- + +### Workflow 4: 批量多平台抓取 + +同时从多个来源抓取数据: + +**步骤 1** — 列出所有抓取任务 +**步骤 2** — 并行启动多个 Actor +**步骤 3** — 等待所有任务完成 +**步骤 4** — 合并结果并去重 + +```python +import asyncio +from apify_client import ApifyClientAsync + +async def batch_scrape(tasks): + client = ApifyClientAsync(os.environ['APIFY_TOKEN']) + results = {} + + async def run_actor(name, actor_id, input_data): + run = await client.actor(actor_id).call(run_input=input_data) + items = [] + async for item in client.dataset(run["defaultDatasetId"]).iterate_items(): + items.append(item) + results[name] = items + + await asyncio.gather(*[ + run_actor(t['name'], t['actor_id'], t['input']) + for t in tasks + ]) + + return results +``` + +--- + +## Output Format + +### JSON 输出(默认) + +```json +{ + "metadata": { + "actor": "apify/instagram-profile-scraper", + "total_items": 42, + "scraped_at": "2025-03-01T14:30:00Z", + "run_id": "abc123", + "cost_usd": 0.05 + }, + "data": [ + { + "id": "post_12345", + "text": "帖子内容...", + "likes": 1234, + "comments": 56, + "timestamp": "2025-02-28T10:00:00Z", + "url": "https://instagram.com/p/xxx" + } + ] +} +``` + +### CSV 输出 + +```python +import pandas as pd + +df = pd.DataFrame(items) +df.to_csv('output.csv', index=False, encoding='utf-8-sig') +``` + +### 摘要表格 + +当数据量较大时,先输出摘要统计: + +``` +📊 抓取完成 +- Actor: Instagram Profile Scraper +- 总条数: 142 条帖子 +- 时间范围: 2025-01-01 ~ 2025-03-01 +- 平均点赞: 2,345 +- 最高互动帖子: [URL] +- 费用: $0.12 +``` + +--- + +## Common Pitfalls + +### 1. APIFY_TOKEN 未配置 + +**症状**:所有请求返回 401 +**解决**:确认 `.env` 中的 `APIFY_TOKEN` 已正确设置 + +### 2. Actor 运行超时 + +**症状**:任务长时间未完成 +**解决**: +- 减少 `maxRequestsPerCrawl` 或 `resultsLimit` +- 使用 `memoryMbytes` 增加内存分配 +- 检查目标网站是否可达 + +### 3. 被目标网站封禁 + +**症状**:返回 403 或空结果 +**解决**: +- 使用 Apify 的代理池(Actor 通常自带) +- 降低并发和频率 +- 增加请求间隔 + +### 4. 数据格式不一致 + +不同 Actor 返回的数据结构不同。在处理数据前先检查字段: + +```python +if items: + print("Available fields:", list(items[0].keys())) +``` + +### 5. 费用超预期 + +Apify 按计算单元(CU)收费。大规模抓取前: +- 先小量测试(`resultsLimit: 10`)确认结果质量 +- 估算总费用:查看测试运行的 CU 消耗 × 总数据量倍数 +- 设置账户费用上限 + +### 6. 社交平台反爬限制 + +Instagram、TikTok 等平台会动态调整反爬策略: +- 不要在短时间内大量抓取同一账号 +- 使用平台提供的数据导出功能作为补充 +- 遵守平台的 robots.txt 和 Terms of Service + +--- + +## 伦理与合规指南 + +### 必须遵守 + +1. **robots.txt** — 尊重网站的 robots.txt 规则 +2. **Terms of Service** — 不违反目标网站的服务条款 +3. **隐私法规** — 遵守 GDPR、个人信息保护法等法规 +4. **频率限制** — 不对目标网站造成过大负载 +5. **数据用途** — 仅用于合法目的(分析、研究、商业决策) + +### 禁止行为 + +1. 抓取个人隐私信息用于骚扰或监控 +2. 大量抓取导致目标网站服务降级 +3. 绕过付费墙或版权保护 +4. 出售未经授权的第三方数据 +5. 用于垃圾信息、虚假评论等恶意目的 + +### 建议做法 + +1. 缓存已获取数据,避免重复抓取 +2. 使用增量抓取而非全量抓取 +3. 在非高峰时段执行大规模任务 +4. 提供 User-Agent 标识你的爬虫身份 +5. 记录抓取日志以便审计 + +--- + +## 高级功能 + +### 定时任务 + +```python +schedule_input = { + "actorId": "apify/google-search-scraper", + "cronExpression": "0 9 * * 1", # 每周一早 9 点 + "input": { + "queries": "竞品动态", + "maxPagesPerQuery": 1, + } +} +``` + +### Webhook 通知 + +```python +run = client.actor("apify/web-scraper").call( + run_input=run_input, + webhooks=[{ + "eventTypes": ["ACTOR.RUN.SUCCEEDED"], + "requestUrl": "https://your-server.com/webhook", + }] +) +``` + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 常用的 Actor ID 和预设配置 +- 自定义数据处理管道 +- 特定网站的抓取策略 +- 代理配置和反封禁策略 diff --git a/account/admin/skills/baoyu-article-illustrator/.openakita-i18n.json b/account/admin/skills/baoyu-article-illustrator/.openakita-i18n.json new file mode 100644 index 0000000..9c869e1 --- /dev/null +++ b/account/admin/skills/baoyu-article-illustrator/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "文章配图", + "description": "智能分析文章结构,自动识别配图位置,Type×Style双维度生成一致风格插图" + } +} diff --git a/account/admin/skills/baoyu-article-illustrator/SKILL.md b/account/admin/skills/baoyu-article-illustrator/SKILL.md new file mode 100644 index 0000000..ab88d5f --- /dev/null +++ b/account/admin/skills/baoyu-article-illustrator/SKILL.md @@ -0,0 +1,155 @@ +--- +name: jimliu/baoyu-skills@baoyu-article-illustrator +description: Analyzes article structure, identifies positions requiring visual aids, generates illustrations with Type × Style two-dimension approach. Use when user asks to "illustrate article", "add images", "generate images for article", or "为文章配图". +--- + +# Article Illustrator + +Analyze articles, identify illustration positions, generate images with Type × Style consistency. + +## Two Dimensions + +| Dimension | Controls | Examples | +|-----------|----------|----------| +| **Type** | Information structure | infographic, scene, flowchart, comparison, framework, timeline | +| **Style** | Visual aesthetics | notion, warm, minimal, blueprint, watercolor, elegant | + +Combine freely: `--type infographic --style blueprint` + +## Types + +| Type | Best For | +|------|----------| +| `infographic` | Data, metrics, technical | +| `scene` | Narratives, emotional | +| `flowchart` | Processes, workflows | +| `comparison` | Side-by-side, options | +| `framework` | Models, architecture | +| `timeline` | History, evolution | + +## Styles + +See [references/styles.md](references/styles.md) for Core Styles, full gallery, and Type × Style compatibility. + +## Workflow + +``` +- [ ] Step 1: Pre-check (EXTEND.md, references, config) +- [ ] Step 2: Analyze content +- [ ] Step 3: Confirm settings (AskUserQuestion) +- [ ] Step 4: Generate outline +- [ ] Step 5: Generate images +- [ ] Step 6: Finalize +``` + +### Step 1: Pre-check + +**1.5 Load Preferences (EXTEND.md) ⛔ BLOCKING** + +```bash +test -f .baoyu-skills/baoyu-article-illustrator/EXTEND.md && echo "project" +test -f "$HOME/.baoyu-skills/baoyu-article-illustrator/EXTEND.md" && echo "user" +``` + +| Result | Action | +|--------|--------| +| Found | Read, parse, display summary | +| Not found | ⛔ Run [first-time-setup](references/config/first-time-setup.md) | + +Full procedures: [references/workflow.md](references/workflow.md#step-1-pre-check) + +### Step 2: Analyze + +| Analysis | Output | +|----------|--------| +| Content type | Technical / Tutorial / Methodology / Narrative | +| Purpose | information / visualization / imagination | +| Core arguments | 2-5 main points | +| Positions | Where illustrations add value | + +**CRITICAL**: Metaphors → visualize underlying concept, NOT literal image. + +Full procedures: [references/workflow.md](references/workflow.md#step-2-setup--analyze) + +### Step 3: Confirm Settings ⚠️ + +**ONE AskUserQuestion, max 4 Qs. Q1-Q3 REQUIRED.** + +| Q | Options | +|---|---------| +| **Q1: Type** | [Recommended], infographic, scene, flowchart, comparison, framework, timeline, mixed | +| **Q2: Density** | minimal (1-2), balanced (3-5), per-section (Recommended), rich (6+) | +| **Q3: Style** | [Recommended], minimal-flat, sci-fi, hand-drawn, editorial, scene, Other | +| Q4: Language | When article language ≠ EXTEND.md setting | + +Full procedures: [references/workflow.md](references/workflow.md#step-3-confirm-settings-) + +### Step 4: Generate Outline + +Save `outline.md` with frontmatter (type, density, style, image_count) and entries: + +```yaml +## Illustration 1 +**Position**: [section/paragraph] +**Purpose**: [why] +**Visual Content**: [what] +**Filename**: 01-infographic-concept-name.png +``` + +Full template: [references/workflow.md](references/workflow.md#step-4-generate-outline) + +### Step 5: Generate Images + +⛔ **BLOCKING: Prompt files MUST be saved before ANY image generation.** + +1. For each illustration, create a prompt file per [references/prompt-construction.md](references/prompt-construction.md) +2. Save to `prompts/NN-{type}-{slug}.md` with YAML frontmatter +3. Prompts **MUST** use type-specific templates with structured sections (ZONES / LABELS / COLORS / STYLE / ASPECT) +4. LABELS **MUST** include article-specific data: actual numbers, terms, metrics, quotes +5. **DO NOT** pass ad-hoc inline prompts to `--prompt` without saving prompt files first +6. Select generation skill, process references (`direct`/`style`/`palette`) +7. Apply watermark if EXTEND.md enabled +8. Generate from saved prompt files; retry once on failure + +Full procedures: [references/workflow.md](references/workflow.md#step-5-generate-images) + +### Step 6: Finalize + +Insert `![description](path/NN-{type}-{slug}.png)` after paragraphs. + +``` +Article Illustration Complete! +Article: [path] | Type: [type] | Density: [level] | Style: [style] +Images: X/N generated +``` + +## Output Directory + +``` +illustrations/{topic-slug}/ +├── source-{slug}.{ext} +├── references/ # if provided +├── outline.md +├── prompts/ +└── NN-{type}-{slug}.png +``` + +**Slug**: 2-4 words, kebab-case. **Conflict**: append `-YYYYMMDD-HHMMSS`. + +## Modification + +| Action | Steps | +|--------|-------| +| Edit | Update prompt → Regenerate → Update reference | +| Add | Position → Prompt → Generate → Update outline → Insert | +| Delete | Delete files → Remove reference → Update outline | + +## References + +| File | Content | +|------|---------| +| [references/workflow.md](references/workflow.md) | Detailed procedures | +| [references/usage.md](references/usage.md) | Command syntax | +| [references/styles.md](references/styles.md) | Style gallery | +| [references/prompt-construction.md](references/prompt-construction.md) | Prompt templates | +| [references/config/first-time-setup.md](references/config/first-time-setup.md) | First-time setup | diff --git a/account/admin/skills/baoyu-comic/.openakita-i18n.json b/account/admin/skills/baoyu-comic/.openakita-i18n.json new file mode 100644 index 0000000..d61d3e7 --- /dev/null +++ b/account/admin/skills/baoyu-comic/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "知识漫画", + "description": "知识漫画创作,支持清线/日漫/写实/水墨/粉笔多种画风,可自动合成PDF" + } +} diff --git a/account/admin/skills/baoyu-comic/SKILL.md b/account/admin/skills/baoyu-comic/SKILL.md new file mode 100644 index 0000000..f0a5c74 --- /dev/null +++ b/account/admin/skills/baoyu-comic/SKILL.md @@ -0,0 +1,306 @@ +--- +name: jimliu/baoyu-skills@baoyu-comic +description: Knowledge comic creator supporting multiple art styles and tones. Creates original educational comics with detailed panel layouts and sequential image generation. Use when user asks to create "知识漫画", "教育漫画", "biography comic", "tutorial comic", or "Logicomix-style comic". +--- + +# Knowledge Comic Creator + +Create original knowledge comics with flexible art style × tone combinations. + +## Usage + +```bash +/baoyu-comic posts/turing-story/source.md +/baoyu-comic article.md --art manga --tone warm +/baoyu-comic # then paste content +``` + +## Options + +### Visual Dimensions + +| Option | Values | Description | +|--------|--------|-------------| +| `--art` | ligne-claire (default), manga, realistic, ink-brush, chalk | Art style / rendering technique | +| `--tone` | neutral (default), warm, dramatic, romantic, energetic, vintage, action | Mood / atmosphere | +| `--layout` | standard (default), cinematic, dense, splash, mixed, webtoon | Panel arrangement | +| `--aspect` | 3:4 (default, portrait), 4:3 (landscape), 16:9 (widescreen) | Page aspect ratio | +| `--lang` | auto (default), zh, en, ja, etc. | Output language | + +### Partial Workflow Options + +| Option | Description | +|--------|-------------| +| `--storyboard-only` | Generate storyboard only, skip prompts and images | +| `--prompts-only` | Generate storyboard + prompts, skip images | +| `--images-only` | Generate images from existing prompts directory | +| `--regenerate N` | Regenerate specific page(s) only (e.g., `3` or `2,5,8`) | + +Details: [references/partial-workflows.md](references/partial-workflows.md) + +### Art Styles (画风) + +| Style | 中文 | Description | +|-------|------|-------------| +| `ligne-claire` | 清线 | Uniform lines, flat colors, European comic tradition (Tintin, Logicomix) | +| `manga` | 日漫 | Large eyes, manga conventions, expressive emotions | +| `realistic` | 写实 | Digital painting, realistic proportions, sophisticated | +| `ink-brush` | 水墨 | Chinese brush strokes, ink wash effects | +| `chalk` | 粉笔 | Chalkboard aesthetic, hand-drawn warmth | + +### Tones (基调) + +| Tone | 中文 | Description | +|------|------|-------------| +| `neutral` | 中性 | Balanced, rational, educational | +| `warm` | 温馨 | Nostalgic, personal, comforting | +| `dramatic` | 戏剧 | High contrast, intense, powerful | +| `romantic` | 浪漫 | Soft, beautiful, decorative elements | +| `energetic` | 活力 | Bright, dynamic, exciting | +| `vintage` | 复古 | Historical, aged, period authenticity | +| `action` | 动作 | Speed lines, impact effects, combat | + +### Preset Shortcuts + +Presets with special rules beyond art+tone: + +| Preset | Equivalent | Special Rules | +|--------|-----------|---------------| +| `--style ohmsha` | `--art manga --tone neutral` | Visual metaphors, NO talking heads, gadget reveals | +| `--style wuxia` | `--art ink-brush --tone action` | Qi effects, combat visuals, atmospheric elements | +| `--style shoujo` | `--art manga --tone romantic` | Decorative elements, eye details, romantic beats | + +### Compatibility Matrix + +| Art Style | ✓✓ Best | ✓ Works | ✗ Avoid | +|-----------|---------|---------|---------| +| ligne-claire | neutral, warm | dramatic, vintage, energetic | romantic, action | +| manga | neutral, romantic, energetic, action | warm, dramatic | vintage | +| realistic | neutral, warm, dramatic, vintage | action | romantic, energetic | +| ink-brush | neutral, dramatic, action, vintage | warm | romantic, energetic | +| chalk | neutral, warm, energetic | vintage | dramatic, action, romantic | + +Details: [references/auto-selection.md](references/auto-selection.md) + +## Auto Selection + +Content signals determine default art + tone + layout (or preset): + +| Content Signals | Recommended | +|-----------------|-------------| +| Tutorial, how-to, programming, educational | **ohmsha** preset | +| Pre-1950, classical, ancient | realistic + vintage | +| Personal story, mentor | ligne-claire + warm | +| Martial arts, wuxia | **wuxia** preset | +| Romance, school life | **shoujo** preset | +| Biography, balanced | ligne-claire + neutral | + +**When preset is recommended**: Load `references/presets/{preset}.md` and apply all special rules. + +Details: [references/auto-selection.md](references/auto-selection.md) + +## Script Directory + +**Important**: All scripts are located in the `scripts/` subdirectory of this skill. + +**Agent Execution Instructions**: +1. Determine this SKILL.md file's directory path as `SKILL_DIR` +2. Script path = `${SKILL_DIR}/scripts/.ts` +3. Replace all `${SKILL_DIR}` in this document with the actual path + +**Script Reference**: +| Script | Purpose | +|--------|---------| +| `scripts/merge-to-pdf.ts` | Merge comic pages into PDF | + +## File Structure + +Output directory: `comic/{topic-slug}/` +- Slug: 2-4 words kebab-case from topic (e.g., `alan-turing-bio`) +- Conflict: append timestamp (e.g., `turing-story-20260118-143052`) + +**Contents**: +| File | Description | +|------|-------------| +| `source-{slug}.{ext}` | Source files | +| `analysis.md` | Content analysis | +| `storyboard.md` | Storyboard with panel breakdown | +| `characters/characters.md` | Character definitions | +| `characters/characters.png` | Character reference sheet | +| `prompts/NN-{cover\|page}-[slug].md` | Generation prompts | +| `NN-{cover\|page}-[slug].png` | Generated images | +| `{topic-slug}.pdf` | Final merged PDF | + +## Language Handling + +**Detection Priority**: +1. `--lang` flag (explicit) +2. EXTEND.md `language` setting +3. User's conversation language +4. Source content language + +**Rule**: Use user's input language or saved language preference for ALL interactions: +- Storyboard outlines and scene descriptions +- Image generation prompts +- User selection options and confirmations +- Progress updates, questions, errors, summaries + +Technical terms remain in English. + +## Workflow + +### Progress Checklist + +``` +Comic Progress: +- [ ] Step 1: Setup & Analyze + - [ ] 1.1 Preferences (EXTEND.md) ⛔ BLOCKING + - [ ] Found → load preferences → continue + - [ ] Not found → run first-time setup → MUST complete before other steps + - [ ] 1.2 Analyze, 1.3 Check existing +- [ ] Step 2: Confirmation - Style & options ⚠️ REQUIRED +- [ ] Step 3: Generate storyboard + characters +- [ ] Step 4: Review outline (conditional) +- [ ] Step 5: Generate prompts +- [ ] Step 6: Review prompts (conditional) +- [ ] Step 7: Generate images ⚠️ CHARACTER REF REQUIRED + - [ ] 7.1 Generate character sheet FIRST → characters/characters.png + - [ ] 7.2 Generate pages WITH --ref characters/characters.png +- [ ] Step 8: Merge to PDF +- [ ] Step 9: Completion report +``` + +### Flow + +``` +Input → [Preferences] ─┬─ Found → Continue + │ + └─ Not found → First-Time Setup ⛔ BLOCKING + │ + └─ Complete setup → Save EXTEND.md → Continue + │ + ┌─────────────────────────────────────────────────────────────────────┘ + ↓ +Analyze → [Check Existing?] → [Confirm: Style + Reviews] → Storyboard → [Review?] → Prompts → [Review?] → Images → PDF → Complete +``` + +### Step Summary + +| Step | Action | Key Output | +|------|--------|------------| +| 1.1 | Load EXTEND.md preferences ⛔ BLOCKING if not found | Config loaded | +| 1.2 | Analyze content | `analysis.md` | +| 1.3 | Check existing directory | Handle conflicts | +| 2 | Confirm style, focus, audience, reviews | User preferences | +| 3 | Generate storyboard + characters | `storyboard.md`, `characters/` | +| 4 | Review outline (if requested) | User approval | +| 5 | Generate prompts | `prompts/*.md` | +| 6 | Review prompts (if requested) | User approval | +| **7.1** | **Generate character sheet FIRST** | `characters/characters.png` | +| **7.2** | Generate pages **with character ref** | `*.png` files | +| 8 | Merge to PDF | `{slug}.pdf` | +| 9 | Completion report | Summary | + +### Step 7: Image Generation ⚠️ CRITICAL + +**Character reference is MANDATORY for visual consistency.** + +**7.1 Generate character sheet first**: +- **Backup rule**: If `characters/characters.png` exists, rename to `characters/characters-backup-YYYYMMDD-HHMMSS.png` +```bash +# Use Reference Sheet Prompt from characters/characters.md +npx -y bun ${SKILL_DIR}/../baoyu-image-gen/scripts/main.ts \ + --promptfiles characters/characters.md \ + --image characters/characters.png --ar 4:3 +``` + +**Compress character sheet** (recommended): +Compress to reduce token usage when used as reference image: +- Use available image compression skill (if any) +- Or system tools: `pngquant`, `optipng`, `sips` (macOS) +- **Keep PNG format**, lossless compression preferred + +**7.2 Generate each page WITH character reference**: + +| Skill Capability | Strategy | +|------------------|----------| +| Supports `--ref` | Pass `characters/characters.png` with EVERY page | +| No `--ref` support | Prepend character descriptions to EVERY prompt file | + +**Backup rules for page generation**: +- If prompt file exists: rename to `prompts/NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.md` +- If image file exists: rename to `NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.png` + +```bash +# Example: ALWAYS include --ref for consistency +npx -y bun ${SKILL_DIR}/../baoyu-image-gen/scripts/main.ts \ + --promptfiles prompts/01-page-xxx.md \ + --image 01-page-xxx.png --ar 3:4 \ + --ref characters/characters.png +``` + +**Full workflow details**: [references/workflow.md](references/workflow.md) + +### EXTEND.md Paths ⛔ BLOCKING + +**CRITICAL**: If EXTEND.md not found, MUST complete first-time setup before ANY other questions or steps. Do NOT proceed to content analysis, do NOT ask about art style, do NOT ask about tone — ONLY complete the preferences setup first. + +| Path | Location | +|------|----------| +| `.baoyu-skills/baoyu-comic/EXTEND.md` | Project directory | +| `$HOME/.baoyu-skills/baoyu-comic/EXTEND.md` | User home | + +| Result | Action | +|--------|--------| +| Found | Read, parse, display summary → Continue | +| Not found | ⛔ **BLOCKING**: Run first-time setup ONLY ([references/config/first-time-setup.md](references/config/first-time-setup.md)) → Complete and save EXTEND.md → Then continue | + +**EXTEND.md Supports**: Watermark | Preferred art/tone/layout | Custom style definitions | Character presets | Language preference + +Schema: [references/config/preferences-schema.md](references/config/preferences-schema.md) + +## References + +**Core Templates**: +- [analysis-framework.md](references/analysis-framework.md) - Deep content analysis +- [character-template.md](references/character-template.md) - Character definition format +- [storyboard-template.md](references/storyboard-template.md) - Storyboard structure +- [ohmsha-guide.md](references/ohmsha-guide.md) - Ohmsha manga specifics + +**Style Definitions**: +- `references/art-styles/` - Art styles (ligne-claire, manga, realistic, ink-brush, chalk) +- `references/tones/` - Tones (neutral, warm, dramatic, romantic, energetic, vintage, action) +- `references/presets/` - Presets with special rules (ohmsha, wuxia, shoujo) +- `references/layouts/` - Layouts (standard, cinematic, dense, splash, mixed, webtoon) + +**Workflow**: +- [workflow.md](references/workflow.md) - Full workflow details +- [auto-selection.md](references/auto-selection.md) - Content signal analysis +- [partial-workflows.md](references/partial-workflows.md) - Partial workflow options + +**Config**: +- [config/preferences-schema.md](references/config/preferences-schema.md) - EXTEND.md schema +- [config/first-time-setup.md](references/config/first-time-setup.md) - First-time setup +- [config/watermark-guide.md](references/config/watermark-guide.md) - Watermark configuration + +## Page Modification + +| Action | Steps | +|--------|-------| +| **Edit** | **Update prompt file FIRST** → `--regenerate N` → Regenerate PDF | +| **Add** | Create prompt at position → Generate with character ref → Renumber subsequent → Update storyboard → Regenerate PDF | +| **Delete** | Remove files → Renumber subsequent → Update storyboard → Regenerate PDF | + +**IMPORTANT**: When updating pages, ALWAYS update the prompt file (`prompts/NN-{cover|page}-[slug].md`) FIRST before regenerating. This ensures changes are documented and reproducible. + +## Notes + +- Image generation: 10-30 seconds per page +- Auto-retry once on generation failure +- Use stylized alternatives for sensitive public figures +- Maintain style consistency via session ID +- **Step 2 confirmation required** - do not skip +- **Steps 4/6 conditional** - only if user requested in Step 2 +- **Step 7.1 character sheet MUST be generated before pages** - ensures consistency +- **Step 7.2 EVERY page MUST reference characters** - use `--ref` or embed descriptions +- Watermark/language configured once in EXTEND.md diff --git a/account/admin/skills/baoyu-cover-image/.openakita-i18n.json b/account/admin/skills/baoyu-cover-image/.openakita-i18n.json new file mode 100644 index 0000000..211f686 --- /dev/null +++ b/account/admin/skills/baoyu-cover-image/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "文章封面图", + "description": "5维度定制文章封面图,支持9种色板和6种渲染风格,电影级/宽屏/方形比例" + } +} diff --git a/account/admin/skills/baoyu-cover-image/SKILL.md b/account/admin/skills/baoyu-cover-image/SKILL.md new file mode 100644 index 0000000..2942d3e --- /dev/null +++ b/account/admin/skills/baoyu-cover-image/SKILL.md @@ -0,0 +1,233 @@ +--- +name: jimliu/baoyu-skills@baoyu-cover-image +description: Generates article cover images with 5 dimensions (type, palette, rendering, text, mood) combining 9 color palettes and 6 rendering styles. Supports cinematic (2.35:1), widescreen (16:9), and square (1:1) aspects. Use when user asks to "generate cover image", "create article cover", or "make cover". +--- + +# Cover Image Generator + +Generate elegant cover images for articles with 5-dimensional customization. + +## Usage + +```bash +# Auto-select dimensions based on content +/baoyu-cover-image path/to/article.md + +# Quick mode: skip confirmation +/baoyu-cover-image article.md --quick + +# Specify dimensions +/baoyu-cover-image article.md --type conceptual --palette warm --rendering flat-vector + +# Style presets (shorthand for palette + rendering) +/baoyu-cover-image article.md --style blueprint + +# With reference images +/baoyu-cover-image article.md --ref style-ref.png + +# Direct content input +/baoyu-cover-image --palette mono --aspect 1:1 --quick +[paste content] +``` + +## Options + +| Option | Description | +|--------|-------------| +| `--type ` | hero, conceptual, typography, metaphor, scene, minimal | +| `--palette ` | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro | +| `--rendering ` | flat-vector, hand-drawn, painterly, digital, pixel, chalk | +| `--style ` | Preset shorthand (see [Style Presets](references/style-presets.md)) | +| `--text ` | none, title-only, title-subtitle, text-rich | +| `--mood ` | subtle, balanced, bold | +| `--font ` | clean, handwritten, serif, display | +| `--aspect ` | 16:9 (default), 2.35:1, 4:3, 3:2, 1:1, 3:4 | +| `--lang ` | Title language (en, zh, ja, etc.) | +| `--no-title` | Alias for `--text none` | +| `--quick` | Skip confirmation, use auto-selection | +| `--ref ` | Reference images for style/composition guidance | + +## Five Dimensions + +| Dimension | Values | Default | +|-----------|--------|---------| +| **Type** | hero, conceptual, typography, metaphor, scene, minimal | auto | +| **Palette** | warm, elegant, cool, dark, earth, vivid, pastel, mono, retro | auto | +| **Rendering** | flat-vector, hand-drawn, painterly, digital, pixel, chalk | auto | +| **Text** | none, title-only, title-subtitle, text-rich | title-only | +| **Mood** | subtle, balanced, bold | balanced | +| **Font** | clean, handwritten, serif, display | clean | + +Auto-selection rules: [references/auto-selection.md](references/auto-selection.md) + +## Galleries + +**Types**: hero, conceptual, typography, metaphor, scene, minimal +→ Details: [references/types.md](references/types.md) + +**Palettes**: warm, elegant, cool, dark, earth, vivid, pastel, mono, retro +→ Details: [references/palettes/](references/palettes/) + +**Renderings**: flat-vector, hand-drawn, painterly, digital, pixel, chalk +→ Details: [references/renderings/](references/renderings/) + +**Text Levels**: none (pure visual) | title-only (default) | title-subtitle | text-rich (with tags) +→ Details: [references/dimensions/text.md](references/dimensions/text.md) + +**Mood Levels**: subtle (low contrast) | balanced (default) | bold (high contrast) +→ Details: [references/dimensions/mood.md](references/dimensions/mood.md) + +**Fonts**: clean (sans-serif) | handwritten | serif | display (bold decorative) +→ Details: [references/dimensions/font.md](references/dimensions/font.md) + +## File Structure + +Output directory per `default_output_dir` preference: +- `same-dir`: `{article-dir}/` +- `imgs-subdir`: `{article-dir}/imgs/` +- `independent` (default): `cover-image/{topic-slug}/` + +``` +/ +├── source-{slug}.{ext} # Source files +├── refs/ # Reference images (if provided) +│ ├── ref-01-{slug}.{ext} +│ └── ref-01-{slug}.md # Description file +├── prompts/cover.md # Generation prompt +└── cover.png # Output image +``` + +**Slug**: 2-4 words, kebab-case. Conflict: append `-YYYYMMDD-HHMMSS` + +## Workflow + +### Progress Checklist + +``` +Cover Image Progress: +- [ ] Step 0: Check preferences (EXTEND.md) ⛔ BLOCKING +- [ ] Step 1: Analyze content + save refs + determine output dir +- [ ] Step 2: Confirm options (6 dimensions) ⚠️ unless --quick +- [ ] Step 3: Create prompt +- [ ] Step 4: Generate image +- [ ] Step 5: Completion report +``` + +### Flow + +``` +Input → [Step 0: Preferences] ─┬─ Found → Continue + └─ Not found → First-Time Setup ⛔ BLOCKING → Save EXTEND.md → Continue + ↓ +Analyze + Save Refs → [Output Dir] → [Confirm: 6 Dimensions] → Prompt → Generate → Complete + ↓ + (skip if --quick or all specified) +``` + +### Step 0: Load Preferences ⛔ BLOCKING + +Check EXTEND.md existence (priority: project → user): +```bash +test -f .baoyu-skills/baoyu-cover-image/EXTEND.md && echo "project" +test -f "$HOME/.baoyu-skills/baoyu-cover-image/EXTEND.md" && echo "user" +``` + +| Result | Action | +|--------|--------| +| Found | Load, display summary → Continue | +| Not found | ⛔ Run first-time setup ([references/config/first-time-setup.md](references/config/first-time-setup.md)) → Save → Continue | + +**CRITICAL**: If not found, complete setup BEFORE any other steps or questions. + +### Step 1: Analyze Content + +1. **Save reference images** (if provided) → [references/workflow/reference-images.md](references/workflow/reference-images.md) +2. **Save source content** (if pasted, save to `source.md`) +3. **Analyze content**: topic, tone, keywords, visual metaphors +4. **Deep analyze references** ⚠️: Extract specific, concrete elements (see reference-images.md) +5. **Detect language**: Compare source, user input, EXTEND.md preference +6. **Determine output directory**: Per File Structure rules + +### Step 2: Confirm Options ⚠️ + +Full confirmation flow: [references/workflow/confirm-options.md](references/workflow/confirm-options.md) + +| Condition | Skipped | Still Asked | +|-----------|---------|-------------| +| `--quick` or `quick_mode: true` | 6 dimensions | Aspect ratio (unless `--aspect`) | +| All 6 + `--aspect` specified | All | None | + +### Step 3: Create Prompt + +Save to `prompts/cover.md`. Template: [references/workflow/prompt-template.md](references/workflow/prompt-template.md) + +**CRITICAL - References in Frontmatter**: +- Files saved to `refs/` → Add to frontmatter `references` list +- Style extracted verbally (no file) → Omit `references`, describe in body +- Before writing → Verify: `test -f refs/ref-NN-{slug}.{ext}` + +**Reference elements in body** MUST be detailed, prefixed with "MUST"/"REQUIRED", with integration approach. + +### Step 4: Generate Image + +1. **Backup existing** `cover.png` if regenerating +2. **Check image generation skills**; if multiple, ask preference +3. **Process references** from prompt frontmatter: + - `direct` usage → pass via `--ref` (use ref-capable backend) + - `style`/`palette` → extract traits, append to prompt +4. **Generate**: Call skill with prompt file, output path, aspect ratio +5. On failure: auto-retry once + +### Step 5: Completion Report + +``` +Cover Generated! + +Topic: [topic] +Type: [type] | Palette: [palette] | Rendering: [rendering] +Text: [text] | Mood: [mood] | Font: [font] | Aspect: [ratio] +Title: [title or "visual only"] +Language: [lang] | Watermark: [enabled/disabled] +References: [N images or "extracted style" or "none"] +Location: [directory path] + +Files: +✓ source-{slug}.{ext} +✓ prompts/cover.md +✓ cover.png +``` + +## Image Modification + +| Action | Steps | +|--------|-------| +| **Regenerate** | Backup → Update prompt file FIRST → Regenerate | +| **Change dimension** | Backup → Confirm new value → Update prompt → Regenerate | + +## Composition Principles + +- **Whitespace**: 40-60% breathing room +- **Visual anchor**: Main element centered or offset left +- **Characters**: Simplified silhouettes; NO realistic humans +- **Title**: Use exact title from user/source; never invent + +## Extension Support + +Custom configurations via EXTEND.md. See **Step 0** for paths. + +Supports: Watermark | Preferred dimensions | Default aspect/output | Quick mode | Custom palettes | Language + +Schema: [references/config/preferences-schema.md](references/config/preferences-schema.md) + +## References + +**Dimensions**: [text.md](references/dimensions/text.md) | [mood.md](references/dimensions/mood.md) | [font.md](references/dimensions/font.md) +**Palettes**: [references/palettes/](references/palettes/) +**Renderings**: [references/renderings/](references/renderings/) +**Types**: [references/types.md](references/types.md) +**Auto-Selection**: [references/auto-selection.md](references/auto-selection.md) +**Style Presets**: [references/style-presets.md](references/style-presets.md) +**Compatibility**: [references/compatibility.md](references/compatibility.md) +**Visual Elements**: [references/visual-elements.md](references/visual-elements.md) +**Workflow**: [confirm-options.md](references/workflow/confirm-options.md) | [prompt-template.md](references/workflow/prompt-template.md) | [reference-images.md](references/workflow/reference-images.md) +**Config**: [preferences-schema.md](references/config/preferences-schema.md) | [first-time-setup.md](references/config/first-time-setup.md) | [watermark-guide.md](references/config/watermark-guide.md) diff --git a/account/admin/skills/baoyu-format-markdown/.openakita-i18n.json b/account/admin/skills/baoyu-format-markdown/.openakita-i18n.json new file mode 100644 index 0000000..92ca9f8 --- /dev/null +++ b/account/admin/skills/baoyu-format-markdown/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Markdown 格式化", + "description": "文本格式化为规范 Markdown,自动添加 frontmatter/标题/加粗/列表,支持中英文排版修复" + } +} diff --git a/account/admin/skills/baoyu-format-markdown/SKILL.md b/account/admin/skills/baoyu-format-markdown/SKILL.md new file mode 100644 index 0000000..f59b708 --- /dev/null +++ b/account/admin/skills/baoyu-format-markdown/SKILL.md @@ -0,0 +1,298 @@ +--- +name: jimliu/baoyu-skills@baoyu-format-markdown +description: Formats plain text or markdown files with frontmatter, titles, summaries, headings, bold, lists, and code blocks. Use when user asks to "format markdown", "beautify article", "add formatting", or improve article layout. Outputs to {filename}-formatted.md. +--- + +# Markdown Formatter + +Transforms plain text or markdown files into well-structured markdown with proper frontmatter, formatting, and typography. + +## Script Directory + +Scripts in `scripts/` subdirectory. Replace `${SKILL_DIR}` with this SKILL.md's directory path. + +| Script | Purpose | +|--------|---------| +| `scripts/main.ts` | Main entry point with CLI options (uses remark-cjk-friendly for CJK emphasis) | +| `scripts/quotes.ts` | Replace ASCII quotes with fullwidth quotes | +| `scripts/autocorrect.ts` | Add CJK/English spacing via autocorrect | + +## Preferences (EXTEND.md) + +Use Bash to check EXTEND.md existence (priority order): + +```bash +# Check project-level first +test -f .baoyu-skills/baoyu-format-markdown/EXTEND.md && echo "project" + +# Then user-level (cross-platform: $HOME works on macOS/Linux/WSL) +test -f "$HOME/.baoyu-skills/baoyu-format-markdown/EXTEND.md" && echo "user" +``` + +┌──────────────────────────────────────────────────────────┬───────────────────┐ +│ Path │ Location │ +├──────────────────────────────────────────────────────────┼───────────────────┤ +│ .baoyu-skills/baoyu-format-markdown/EXTEND.md │ Project directory │ +├──────────────────────────────────────────────────────────┼───────────────────┤ +│ $HOME/.baoyu-skills/baoyu-format-markdown/EXTEND.md │ User home │ +└──────────────────────────────────────────────────────────┴───────────────────┘ + +┌───────────┬───────────────────────────────────────────────────────────────────────────┐ +│ Result │ Action │ +├───────────┼───────────────────────────────────────────────────────────────────────────┤ +│ Found │ Read, parse, apply settings │ +├───────────┼───────────────────────────────────────────────────────────────────────────┤ +│ Not found │ Use defaults │ +└───────────┴───────────────────────────────────────────────────────────────────────────┘ + +**EXTEND.md Supports**: Default formatting options | Summary length preferences + +## Usage + +Claude performs content analysis and formatting (Steps 1-6), then runs the script for typography fixes (Step 7). + +## Workflow + +### Step 1: Read Source File + +Read the user-specified markdown or plain text file. + +### Step 1.5: Detect Content Type & Confirm + +**Content Type Detection:** + +| Indicator | Classification | +|-----------|----------------| +| Has `---` YAML frontmatter | Markdown | +| Has `#`, `##`, `###` headings | Markdown | +| Has `**bold**`, `*italic*` | Markdown | +| Has `- ` or `1. ` lists | Markdown | +| Has ``` code blocks | Markdown | +| Has `> ` blockquotes | Markdown | +| None of above | Plain text | + +**Decision Flow:** + +┌─────────────────┬────────────────────────────────────────────────┐ +│ Content Type │ Action │ +├─────────────────┼────────────────────────────────────────────────┤ +│ Plain text │ Proceed to Step 2 (format to markdown) │ +├─────────────────┼────────────────────────────────────────────────┤ +│ Markdown │ Use AskUserQuestion to confirm optimization │ +└─────────────────┴────────────────────────────────────────────────┘ + +**If Markdown detected, ask user:** + +``` +Detected existing markdown formatting. What would you like to do? + +1. Optimize formatting (Recommended) + - Add/improve frontmatter, headings, bold, lists + - Run typography script (spacing, emphasis fixes) + - Output: {filename}-formatted.md + +2. Keep original formatting + - Preserve existing markdown structure + - Run typography script (spacing, emphasis fixes) + - Output: {filename}-formatted.md + +3. Typography fixes only + - Run typography script on original file in-place + - No copy created, modifies original file directly +``` + +**Based on user choice:** +- **Optimize**: Continue to Step 2-8 (full workflow) +- **Keep original**: Skip Steps 2-5, copy file → Step 6-8 (run script on copy) +- **Typography only**: Skip Steps 2-6, run Step 7 on original file directly + +### Step 2: Analyze Content Structure + +Identify: +- Existing title (H1 `#`) +- Paragraph separations +- Keywords suitable for **bold** +- Parallel content convertible to lists +- Code snippets +- Quotations + +### Step 3: Check/Create Frontmatter + +Check for YAML frontmatter (`---` block). Create if missing. + +**Meta field handling:** + +| Field | Processing | +|-------|------------| +| `title` | See Step 4 | +| `slug` | Infer from file path (e.g., `posts/2026/01/10/vibe-coding/` → `vibe-coding`) or generate from title | +| `summary` | Generate engaging summary (100-150 characters) | +| `coverImage` | Check if `imgs/cover.png` exists in same directory; if so, use relative path (also accepted: `featureImage`) | + +### Step 4: Title Handling + +**Logic:** +1. If frontmatter already has `title` → use it, no H1 in body +2. If first line is H1 → extract to frontmatter `title`, remove H1 from body +3. If neither exists → generate candidate titles + +**Title generation flow:** + +1. Generate 3 candidate titles based on content +2. Use `AskUserQuestion` tool: + +``` +Select a title: + +1. [Title A] (Recommended) +2. [Title B] +3. [Title C] +``` + +3. If no selection within a few seconds, use recommended (option 1) + +**Title principles:** +- Concise, max 20 characters +- Captures core message +- Engaging, sparks reading interest +- Accurate, avoids clickbait + +**Important:** Once title is in frontmatter, body should NOT have H1 (avoid duplication) + +### Step 5: Format Processing + +**Formatting rules:** + +| Element | Format | +|---------|--------| +| Titles | Use `#`, `##`, `###` hierarchy | +| Key points | Use `**bold**` | +| Parallel items | Convert to `-` unordered or `1.` ordered lists | +| Code/commands | Use `` `inline` `` or ` ```block``` ` | +| Quotes/sayings | Use `>` blockquote | +| Separators | Use `---` where appropriate | + +**Formatting principles:** +- Preserve original content and viewpoints +- Add formatting only, do not modify text +- Formatting serves readability +- Avoid over-formatting + +### Step 6: Save Formatted File + +Save as `{original-filename}-formatted.md` + +Examples: +- `final.md` → `final-formatted.md` +- `draft-v1.md` → `draft-v1-formatted.md` + +**If user chose "Keep original formatting" (from Step 1.5):** +- Copy original file to `{filename}-formatted.md` without modifications +- Proceed to Step 7 for typography fixes only + +**Backup existing file:** + +If `{filename}-formatted.md` already exists, backup before overwriting: + +```bash +# Check if formatted file exists +if [ -f "{filename}-formatted.md" ]; then + # Backup with timestamp + mv "{filename}-formatted.md" "{filename}-formatted.backup-$(date +%Y%m%d-%H%M%S).md" +fi +``` + +Example: +- `final-formatted.md` exists → backup to `final-formatted.backup-20260128-143052.md` + +### Step 7: Execute Text Formatting Script + +After saving, **must** run the formatting script: + +```bash +npx -y bun ${SKILL_DIR}/scripts/main.ts {output-file-path} [options] +``` + +**Script Options:** + +| Option | Short | Description | Default | +|--------|-------|-------------|---------| +| `--quotes` | `-q` | Replace ASCII quotes with fullwidth quotes `"..."` | false | +| `--no-quotes` | | Do not replace quotes | | +| `--spacing` | `-s` | Add CJK/English spacing via autocorrect | true | +| `--no-spacing` | | Do not add CJK/English spacing | | +| `--emphasis` | `-e` | Fix CJK emphasis punctuation issues | true | +| `--no-emphasis` | | Do not fix CJK emphasis issues | | +| `--help` | `-h` | Show help message | | + +**Examples:** + +```bash +# Default: spacing + emphasis enabled, quotes disabled +npx -y bun ${SKILL_DIR}/scripts/main.ts article.md + +# Enable all features including quote replacement +npx -y bun ${SKILL_DIR}/scripts/main.ts article.md --quotes + +# Only fix emphasis issues, skip spacing +npx -y bun ${SKILL_DIR}/scripts/main.ts article.md --no-spacing + +# Disable all processing except frontmatter formatting +npx -y bun ${SKILL_DIR}/scripts/main.ts article.md --no-spacing --no-emphasis +``` + +**Script performs (based on options):** +1. Fix CJK emphasis/bold punctuation issues (default: enabled) +2. Add CJK/English mixed text spacing via autocorrect (default: enabled) +3. Replace ASCII quotes `"..."` with fullwidth quotes `"..."` (default: disabled) +4. Format frontmatter YAML (always enabled) + +### Step 8: Display Results + +``` +**Formatting complete** + +File: posts/2026/01/09/example/final-formatted.md + +Changes: +- Added title: [title content] +- Added X bold markers +- Added X lists +- Added X code blocks +``` + +## Formatting Example + +**Before:** +``` +This is plain text. First point is efficiency improvement. Second point is cost reduction. Third point is experience optimization. Use npm install to install dependencies. +``` + +**After:** +```markdown +--- +title: Three Core Advantages +slug: three-core-advantages +summary: Discover the three key benefits that drive success in modern projects. +--- + +This is plain text. + +**Main advantages:** +- Efficiency improvement +- Cost reduction +- Experience optimization + +Use `npm install` to install dependencies. +``` + +## Notes + +- Preserve original writing style and tone +- Specify correct language for code blocks (e.g., `python`, `javascript`) +- Maintain CJK/English spacing standards +- Do not add content not present in original + +## Extension Support + +Custom configurations via EXTEND.md. See **Preferences** section for paths and supported options. diff --git a/account/admin/skills/baoyu-image-gen/.openakita-i18n.json b/account/admin/skills/baoyu-image-gen/.openakita-i18n.json new file mode 100644 index 0000000..f402b9c --- /dev/null +++ b/account/admin/skills/baoyu-image-gen/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "AI 图像生成", + "description": "多服务商 AI 图像生成(DALL-E、Imagen、通义万象、Replicate),支持多种比例、质量预设、批量生成和 Prompt 优化。" + } +} diff --git a/account/admin/skills/baoyu-image-gen/SKILL.md b/account/admin/skills/baoyu-image-gen/SKILL.md new file mode 100644 index 0000000..384de9d --- /dev/null +++ b/account/admin/skills/baoyu-image-gen/SKILL.md @@ -0,0 +1,377 @@ +--- +name: jimliu/baoyu-skills@baoyu-image-gen +description: Generate AI images using multiple providers (OpenAI DALL-E, Google Imagen, DashScope/Tongyi Wanxiang, Replicate). Supports various aspect ratios, quality presets, batch generation, and provider-specific prompt engineering techniques. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Baoyu Image Gen — AI 图像生成 + +## When to Use + +- 用户要求生成图片、插图、海报、封面、图标等视觉内容 +- 需要为文章、PPT、网站创建配图 +- 需要特定比例的图片(社交媒体封面、手机壁纸等) +- 需要批量生成多张图片并选择 +- 需要针对不同 AI 绘图服务编写优化 prompt +- 需要将自然语言描述转换为高质量 AI 图片 + +--- + +## Prerequisites + +### API 密钥配置 + +至少需要配置一个图像生成服务的 API 密钥。在 `.env` 文件或环境变量中设置: + +| 环境变量 | 服务商 | 获取方式 | +|---------|--------|---------| +| `OPENAI_API_KEY` | OpenAI DALL-E 3 | https://platform.openai.com/api-keys | +| `GOOGLE_API_KEY` | Google Imagen 3 | https://aistudio.google.com/apikey | +| `DASHSCOPE_API_KEY` | 通义万象 (阿里云) | https://dashscope.console.aliyun.com/ | +| `REPLICATE_API_TOKEN` | Replicate (Flux 等) | https://replicate.com/account/api-tokens | + +### 必需依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| Python ≥ 3.10 | 运行生成脚本 | 系统预装 | +| `httpx` | HTTP 请求 | `pip install httpx` | +| `Pillow` | 图片处理 | `pip install Pillow` | + +### 可选依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `openai` | OpenAI SDK | `pip install openai` | +| `google-genai` | Google Gemini/Imagen SDK | `pip install google-genai` | +| `dashscope` | 通义万象 SDK | `pip install dashscope` | +| `replicate` | Replicate SDK | `pip install replicate` | + +--- + +## Instructions + +### 服务商能力对比 + +| 能力 | DALL-E 3 | Imagen 3 | 通义万象 | Replicate (Flux) | +|------|----------|----------|---------|-----------------| +| 图片质量 | ★★★★★ | ★★★★★ | ★★★★ | ★★★★★ | +| 中文 prompt | ★★★ | ★★★ | ★★★★★ | ★★ | +| 文字渲染 | ★★★★ | ★★★★ | ★★★ | ★★★ | +| 速度 | 中等 | 快 | 快 | 慢 | +| 价格 | 较贵 | 中等 | 便宜 | 按模型 | +| 尺寸灵活度 | 3 种固定 | 多种 | 多种 | 自定义 | +| 风格多样性 | ★★★★★ | ★★★★ | ★★★★ | ★★★★★ | + +### 服务商自动选择策略 + +Agent 根据以下规则自动选择最合适的服务商: + +1. **中文场景优先** — 如果 prompt 是中文或涉及中国文化元素,优先使用通义万象 +2. **文字渲染需求** — 需要在图片中嵌入文字时,优先使用 DALL-E 3 或 Imagen 3 +3. **速度优先** — 用户要求快速生成时,优先使用 Imagen 3 或通义万象 +4. **质量优先** — 用户要求最高质量时,使用 DALL-E 3 或 Flux Pro +5. **成本优先** — 批量生成时优先使用通义万象 +6. **可用性** — 根据用户已配置的 API Key 选择 + +用户可通过指定服务商名称覆盖自动选择。 + +### 宽高比速查 + +| 比例 | 像素(示例) | 适用场景 | +|------|-------------|---------| +| 1:1 | 1024×1024 | 头像、图标、社交媒体帖子 | +| 16:9 | 1792×1024 | PPT 配图、YouTube 封面、桌面壁纸 | +| 4:3 | 1365×1024 | 传统幻灯片、相册 | +| 9:16 | 1024×1792 | 手机壁纸、Instagram Stories、短视频封面 | +| 3:2 | 1536×1024 | 摄影风格、杂志插图 | +| 2:3 | 1024×1536 | 海报、书籍封面 | + +### 质量预设 + +| 预设 | 说明 | 适用场景 | +|------|------|---------| +| `draft` | 快速草稿,低分辨率 | 方案探索、快速迭代 | +| `standard` | 标准质量 | 日常使用、网页配图 | +| `hd` | 高清,细节丰富 | 正式出版、印刷 | +| `ultra` | 最高质量,最长等待 | 海报、展览 | + +--- + +## Workflows + +### Workflow 1: 单张图片生成 + +**步骤 1 — 理解用户意图** + +从用户描述中提取以下信息: + +| 要素 | 默认值 | 说明 | +|------|--------|------| +| 主题 | — | 图片的核心内容 | +| 风格 | 写实 | 摄影、插画、水彩、赛博朋克、扁平化等 | +| 比例 | 1:1 | 根据用途自动推断 | +| 质量 | standard | draft/standard/hd/ultra | +| 服务商 | auto | 自动选择或用户指定 | + +**步骤 2 — 构建优化 Prompt** + +将用户描述转换为各服务商优化的 prompt(见 Prompt 工程部分)。 + +**步骤 3 — 调用生成 API** + +根据选择的服务商调用对应 API。 + +**步骤 4 — 返回结果** + +输出生成的图片文件路径,并附上使用的 prompt 和参数。 + +--- + +### Workflow 2: 批量生成 + +一次生成多张图片供用户选择: + +**步骤 1** — 确定批量参数 + +| 参数 | 说明 | +|------|------| +| 数量 | 2-8 张(默认 4) | +| 变体策略 | same-prompt(同 prompt 不同种子)/ varied-prompt(不同风格变体) | + +**步骤 2** — 生成所有图片 + +并行调用 API 以加快速度。对于 varied-prompt 模式,为每张图调整 prompt 的风格描述词。 + +**步骤 3** — 展示结果并让用户选择 + +--- + +### Workflow 3: Prompt 优化咨询 + +当用户不确定如何描述想要的图片时: + +1. 与用户对话,逐步明确需求 +2. 提供 3-5 个不同方向的 prompt 建议 +3. 用户选择方向后微调 prompt +4. 生成图片 + +--- + +## Prompt 工程指南 + +### 通用 Prompt 结构 + +``` +[主体描述], [环境/背景], [风格], [光线], [构图], [色调], [细节描述] +``` + +**示例**: + +``` +A cozy coffee shop interior with warm lighting, +morning sunlight streaming through large windows, +a steaming cup of latte on a wooden table with an open book, +shot on 35mm film, soft warm tones, +shallow depth of field, photorealistic +``` + +### DALL-E 3 专用技巧 + +1. **自然语言描述** — DALL-E 3 理解长句叙述,不需要关键词堆砌 +2. **风格指定** — 明确说明 "digital art"、"oil painting"、"photograph" 等 +3. **避免否定词** — 说"蓝天"而非"没有云的天空" +4. **文字嵌入** — 直接写 `with text "Hello"` 可以在图中渲染文字 +5. **revisedPrompt** — DALL-E 3 会重写 prompt,可从返回值获取实际使用的 prompt + +```python +from openai import OpenAI +client = OpenAI() + +response = client.images.generate( + model="dall-e-3", + prompt="一只橘猫坐在窗台上看雨,窗外是东京夜景,赛博朋克风格,霓虹灯倒映在雨滴中", + size="1792x1024", + quality="hd", + n=1 +) +image_url = response.data[0].url +revised_prompt = response.data[0].revised_prompt +``` + +### Google Imagen 3 专用技巧 + +1. **结构化描述** — 主体 + 动作 + 环境 + 风格 +2. **摄影参数** — 可以指定镜头焦段、光圈、ISO 等 +3. **艺术家风格** — 可以参考知名艺术家的风格 +4. **多语言支持** — 支持中文 prompt 但英文效果更佳 + +```python +from google import genai +client = genai.Client() + +response = client.models.generate_images( + model='imagen-3.0-generate-002', + prompt='A serene Japanese garden in autumn, koi fish swimming in a crystal clear pond, maple trees with red and orange leaves', + config=genai.types.GenerateImagesConfig( + number_of_images=1, + aspect_ratio='16:9' + ) +) + +for image in response.generated_images: + image.image.save('garden.png') +``` + +### 通义万象专用技巧 + +1. **中文 prompt 最优** — 直接使用中文描述效果最佳 +2. **风格参数** — 支持 ``、``、`<3d cartoon>` 等风格标签 +3. **负向提示** — 支持 negative_prompt 排除不想要的元素 +4. **参考图** — 支持 img2img 以图生图 + +```python +import dashscope + +response = dashscope.ImageSynthesis.call( + api_key=os.getenv('DASHSCOPE_API_KEY'), + model='wanx-v1', + input={ + 'prompt': '一座雪山下的小木屋,温暖的灯光从窗户透出,天空中有极光,油画风格', + 'negative_prompt': '低质量, 模糊, 变形' + }, + parameters={ + 'size': '1024*1024', + 'n': 1, + 'style': '' + } +) + +image_url = response.output.results[0].url +``` + +### Replicate (Flux) 专用技巧 + +1. **英文 prompt** — Flux 模型英文效果远优于中文 +2. **极致细节** — 适合描述复杂场景和精细纹理 +3. **风格混搭** — 可以混合多种艺术风格 +4. **自定义参数** — 支持 guidance_scale、steps 等高级参数 + +```python +import replicate + +output = replicate.run( + "black-forest-labs/flux-1.1-pro", + input={ + "prompt": "An astronaut riding a horse on Mars, cinematic lighting, 8k resolution, hyperdetailed", + "aspect_ratio": "16:9", + "output_format": "png", + "safety_tolerance": 2 + } +) +``` + +--- + +## Output Format + +### 文件命名 + +``` +{描述关键词}_{服务商}_{比例}_{日期时间}.png +``` + +示例:`coffee_shop_dalle3_16x9_20250301_143022.png` + +### 输出内容 + +每次图片生成后,返回以下信息: + +``` +📸 图片已生成 +- 文件:./images/coffee_shop_dalle3_16x9.png +- 服务商:DALL-E 3 +- 尺寸:1792 × 1024 (16:9) +- 质量:HD +- Prompt:[实际使用的 prompt] +- 耗时:8.3s +- 费用估算:$0.08 +``` + +### 多图对比输出 + +批量生成时以网格形式对比展示,标注每张的差异(不同风格、不同构图等)。 + +--- + +## Common Pitfalls + +### 1. API Key 未配置 + +**症状**:调用失败,返回 401/403 错误 +**解决**:检查 `.env` 或环境变量中的 API Key 是否已正确设置 + +### 2. Prompt 过于模糊 + +**错误**:"画一张好看的图" +**正确**:"一只白色的猫咪趴在阳光下的窗台上,背景是模糊的绿色植物,温暖的暖色调,胶片摄影风格" + +### 3. 比例与用途不匹配 + +常见错误搭配: +- PPT 配图用了 1:1 → 应该用 16:9 +- 手机壁纸用了 16:9 → 应该用 9:16 +- 社交媒体头像用了 16:9 → 应该用 1:1 + +### 4. 中文 prompt 发给 Flux/Replicate + +Flux 等模型对中文支持有限,必须先翻译为英文再调用。Agent 应自动完成翻译。 + +### 5. 图片中文字乱码 + +AI 图像生成模型在渲染中文文字时质量不稳定。如果必须在图片中嵌入中文文字,建议: +- 先生成不含文字的图片 +- 然后用 Pillow 在图片上叠加中文文字 + +```python +from PIL import Image, ImageDraw, ImageFont + +img = Image.open('base_image.png') +draw = ImageDraw.Draw(img) +font = ImageFont.truetype('msyh.ttc', size=48) +draw.text((100, 50), '标题文字', fill='white', font=font) +img.save('final_image.png') +``` + +### 6. 费用失控 + +批量生成时注意费用: +| 服务商 | 单张费用(约) | +|--------|-------------| +| DALL-E 3 HD | $0.08 | +| DALL-E 3 Standard | $0.04 | +| Imagen 3 | $0.03 | +| 通义万象 | ¥0.04 | +| Flux Pro | $0.05 | + +生成前提醒用户预估费用。 + +### 7. 内容安全限制 + +所有服务商都有内容安全审查。如果生成被拒绝: +- 检查 prompt 是否包含敏感词 +- 调整描述方式 +- 不要尝试绕过安全限制 + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 首选服务商和默认参数 +- 自定义风格预设模板 +- 品牌相关的 prompt 片段(Logo 描述、品牌色等) +- 额外的 API 端点或自部署模型地址 diff --git a/account/admin/skills/baoyu-infographic/.openakita-i18n.json b/account/admin/skills/baoyu-infographic/.openakita-i18n.json new file mode 100644 index 0000000..daa388e --- /dev/null +++ b/account/admin/skills/baoyu-infographic/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "信息图生成", + "description": "专业信息图制作,21种布局×20种视觉风格,自动分析内容并推荐最佳组合" + } +} diff --git a/account/admin/skills/baoyu-infographic/SKILL.md b/account/admin/skills/baoyu-infographic/SKILL.md new file mode 100644 index 0000000..47c0313 --- /dev/null +++ b/account/admin/skills/baoyu-infographic/SKILL.md @@ -0,0 +1,250 @@ +--- +name: jimliu/baoyu-skills@baoyu-infographic +description: Generates professional infographics with 21 layout types and 20 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图". +--- + +# Infographic Generator + +Two dimensions: **layout** (information structure) × **style** (visual aesthetics). Freely combine any layout with any style. + +## Usage + +```bash +/baoyu-infographic path/to/content.md +/baoyu-infographic path/to/content.md --layout hierarchical-layers --style technical-schematic +/baoyu-infographic path/to/content.md --aspect portrait --lang zh +/baoyu-infographic # then paste content +``` + +## Options + +| Option | Values | +|--------|--------| +| `--layout` | 21 options (see Layout Gallery), default: bento-grid | +| `--style` | 20 options (see Style Gallery), default: craft-handmade | +| `--aspect` | landscape (16:9), portrait (9:16), square (1:1) | +| `--lang` | en, zh, ja, etc. | + +## Layout Gallery + +| Layout | Best For | +|--------|----------| +| `linear-progression` | Timelines, processes, tutorials | +| `binary-comparison` | A vs B, before-after, pros-cons | +| `comparison-matrix` | Multi-factor comparisons | +| `hierarchical-layers` | Pyramids, priority levels | +| `tree-branching` | Categories, taxonomies | +| `hub-spoke` | Central concept with related items | +| `structural-breakdown` | Exploded views, cross-sections | +| `bento-grid` | Multiple topics, overview (default) | +| `iceberg` | Surface vs hidden aspects | +| `bridge` | Problem-solution | +| `funnel` | Conversion, filtering | +| `isometric-map` | Spatial relationships | +| `dashboard` | Metrics, KPIs | +| `periodic-table` | Categorized collections | +| `comic-strip` | Narratives, sequences | +| `story-mountain` | Plot structure, tension arcs | +| `jigsaw` | Interconnected parts | +| `venn-diagram` | Overlapping concepts | +| `winding-roadmap` | Journey, milestones | +| `circular-flow` | Cycles, recurring processes | +| `dense-modules` | High-density modules, data-rich guides | + +Full definitions: `references/layouts/.md` + +## Style Gallery + +| Style | Description | +|-------|-------------| +| `craft-handmade` | Hand-drawn, paper craft (default) | +| `claymation` | 3D clay figures, stop-motion | +| `kawaii` | Japanese cute, pastels | +| `storybook-watercolor` | Soft painted, whimsical | +| `chalkboard` | Chalk on black board | +| `cyberpunk-neon` | Neon glow, futuristic | +| `bold-graphic` | Comic style, halftone | +| `aged-academia` | Vintage science, sepia | +| `corporate-memphis` | Flat vector, vibrant | +| `technical-schematic` | Blueprint, engineering | +| `origami` | Folded paper, geometric | +| `pixel-art` | Retro 8-bit | +| `ui-wireframe` | Grayscale interface mockup | +| `subway-map` | Transit diagram | +| `ikea-manual` | Minimal line art | +| `knolling` | Organized flat-lay | +| `lego-brick` | Toy brick construction | +| `pop-laboratory` | Blueprint grid, coordinate markers, lab precision | +| `morandi-journal` | Hand-drawn doodle, warm Morandi tones | +| `retro-pop-grid` | 1970s retro pop art, Swiss grid, thick outlines | + +Full definitions: `references/styles/ + + +
+
+ + +
+

研究主题

+

核心发现的一句话总结

+

基于 N 个来源的综合分析 | YYYY-MM-DD

+
+ + +
+

核心发现

+
+
+
3.5x
+
增长率
+
+
+
78%
+
采纳率
+
+
+

来源: 文档 A, p.12; 文档 B, §3

+
+ + +
+

发现一

+
+

关键发现的详细描述,包含数据支撑和引用。

+
+

来源: 文档 C, Table 2

+
+ + +
+

结论与建议

+
    +
  1. 建议一
  2. +
  3. 建议二
  4. +
  5. 建议三
  6. +
+
+ +
+
+ + + + +``` + +### Mermaid 图表输出 + +适用于流程、关系、架构的可视化。 + +**流程图:** +````markdown +```mermaid +graph TB + A[文档上传] --> B[初始查询] + B --> C{发现足够?} + C -->|否| D[深度追问] + D --> B + C -->|是| E[综合分析] + E --> F[结构化输出] + F --> G[Markdown] + F --> H[HTML/reveal.js] + F --> I[Mermaid 图表] +``` +```` + +**思维导图:** +````markdown +```mermaid +mindmap + root((研究主题)) + 发现一 + 数据点 A + 数据点 B + 发现二 + 论据 C + 论据 D + 发现三 + 趋势 E + 对比 F +``` +```` + +**时间线:** +````markdown +```mermaid +timeline + title 技术发展时间线 + 2020 : 基础模型出现 + : GPT-3 发布 + 2022 : ChatGPT 引爆市场 + : 指令微调成为标准 + 2024 : 多模态模型成熟 + : Agent 架构兴起 + 2025 : 端侧推理普及 + : MCP 协议标准化 +``` +```` + +**实体关系图:** +````markdown +```mermaid +erDiagram + RESEARCH ||--o{ DOCUMENT : "基于" + DOCUMENT ||--o{ FINDING : "包含" + FINDING ||--o{ CITATION : "引用自" + RESEARCH ||--o{ CONCLUSION : "得出" + CONCLUSION }o--|| FINDING : "基于" +``` +```` + +--- + +## 研究质量检查清单 + +### 输出前自检 + +| 检查项 | 标准 | ✅ | +|--------|------|---| +| **引用覆盖** | 每个核心发现都有引用 | | +| **来源多样** | 不依赖单一来源 | | +| **数据准确** | 数字和引文与原文一致 | | +| **逻辑连贯** | 发现之间逻辑自洽 | | +| **信息空白** | 已标注缺失或不确定的部分 | | +| **视觉层次** | 信息图有清晰的阅读路径 | | +| **可操作性** | 结论包含具体建议 | | +| **格式规范** | 输出格式正确、可渲染 | | + +### 研究可信度评估 + +```markdown +## 可信度评估 + +### 来源质量 +- 学术同行评审: X 篇 +- 行业权威报告: X 篇 +- 一手数据: X 篇 +- 二手分析: X 篇 + +### 发现一致性 +- 多来源支持的发现: X 条 +- 单来源发现: X 条 +- 来源间矛盾: X 处 + +### 局限性 +- 时间范围: YYYY 至 YYYY +- 地理范围: +- 样本局限: +- 方法论局限: + +### 综合可信度: 高 / 中 / 低 +``` + +--- + +## 注意事项 + +- **尊重版权** — 引用应遵循合理使用原则,不大段复制原文 +- **标注不确定性** — 推测性结论应明确标注为"推测"或"需进一步验证" +- **区分事实与观点** — 文档中的事实和作者观点应有区分标识 +- **保持中立** — 呈现多方观点,避免选择性引用 +- **检查时效性** — 标注数据的采集时间,提醒读者时效风险 +- **注意文档质量** — 上传前确认文档可读,OCR 文档可能有识别错误 +- **迭代优化** — 第一轮输出后审查引用准确性,必要时回查原文 +- **格式兼容** — reveal.js 幻灯片需确保 CDN 资源可访问 diff --git a/account/admin/skills/obsidian-skills/.openakita-i18n.json b/account/admin/skills/obsidian-skills/.openakita-i18n.json new file mode 100644 index 0000000..db6551e --- /dev/null +++ b/account/admin/skills/obsidian-skills/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Obsidian 笔记管理", + "description": "管理 Obsidian 知识库,支持 Obsidian Flavored Markdown(wikilinks、嵌入、callouts)、YAML 属性、Dataview 查询、Canvas 画布和 Bases 数据库视图,遵循 MOC 和原子笔记最佳实践。" + } +} diff --git a/account/admin/skills/obsidian-skills/SKILL.md b/account/admin/skills/obsidian-skills/SKILL.md new file mode 100644 index 0000000..1b0925c --- /dev/null +++ b/account/admin/skills/obsidian-skills/SKILL.md @@ -0,0 +1,630 @@ +--- +name: openakita/skills@obsidian-skills +description: Manage Obsidian vaults with full support for Obsidian Flavored Markdown — wikilinks, embeds, callouts, YAML properties, Dataview queries, Canvas, and Bases. Organize notes using MOCs (Maps of Content), atomic note principles, and consistent folder/tag taxonomies. Always ask the user where to save before creating notes. +license: MIT +metadata: + author: openakita + version: "1.0.0" + upstream: kepano/obsidian-skills +--- + +# Obsidian 笔记管理技能 + +帮助用户在 Obsidian 知识库中创建、组织和管理笔记,遵循 Obsidian Flavored Markdown(OFM)规范和知识管理最佳实践。 + +--- + +## 核心原则 + +1. **创建笔记前必须询问保存位置** — 永远不要自行假设路径,先确认用户的 Vault 结构和目标文件夹。 +2. **遵循 Obsidian Flavored Markdown** — 使用 wikilinks、嵌入、callouts 等 OFM 专有语法。 +3. **原子笔记** — 每条笔记聚焦一个概念,通过链接建立知识网络。 +4. **元数据驱动** — 使用 YAML frontmatter properties 保证笔记可被检索和查询。 + +--- + +## Obsidian Flavored Markdown 语法参考 + +### Wikilinks(内部链接) + +Obsidian 使用 `[[]]` 语法进行内部链接,这是与标准 Markdown 最重要的区别。 + +```markdown +[[笔记名称]] # 链接到同名笔记 +[[笔记名称|显示文本]] # 自定义显示文本 +[[笔记名称#标题]] # 链接到特定标题 +[[笔记名称#^block-id]] # 链接到特定块 +[[笔记名称#标题|显示文本]] # 标题链接 + 自定义文本 +``` + +**最佳实践:** +- 笔记名称应具有描述性且唯一,避免使用特殊字符 `[ ] # ^ | \` +- 优先使用笔记全名链接而非路径链接,Obsidian 会自动解析 +- 使用别名(alias)而不是 `|显示文本` 来处理频繁使用的缩写 + +### 嵌入(Embeds) + +使用 `![[]]` 语法将其他笔记或资源直接嵌入当前笔记。 + +```markdown +![[笔记名称]] # 嵌入整篇笔记 +![[笔记名称#标题]] # 嵌入特定章节 +![[笔记名称#^block-id]] # 嵌入特定块 +![[图片.png]] # 嵌入图片 +![[图片.png|300]] # 指定宽度 +![[音频.mp3]] # 嵌入音频 +![[视频.mp4]] # 嵌入视频 +![[文档.pdf]] # 嵌入 PDF +![[文档.pdf#page=3]] # 嵌入 PDF 特定页 +``` + +### Callouts(提示框) + +基于 Markdown blockquote 语法扩展,用于高亮重要信息。 + +```markdown +> [!note] 标题 +> 笔记内容 + +> [!tip] 提示 +> 有用的建议 + +> [!warning] 警告 +> 需要注意的事项 + +> [!important] 重要 +> 关键信息 + +> [!info] 信息 +> 补充说明 + +> [!question] 问题 +> 需要进一步探讨的问题 + +> [!example] 示例 +> 具体的例子 + +> [!abstract] 摘要 +> 概述或总结 + +> [!todo] 待办 +> 需要完成的任务 + +> [!quote] 引用 +> 引用来源文字 +``` + +**折叠 Callout:** +```markdown +> [!tip]- 点击展开 # 默认折叠 +> 隐藏内容 + +> [!tip]+ 点击折叠 # 默认展开 +> 可折叠内容 +``` + +**嵌套 Callout:** +```markdown +> [!note] 外层 +> 外层内容 +>> [!tip] 内层 +>> 内层内容 +``` + +### 标签(Tags) + +```markdown +#标签名 # 行内标签 +#父标签/子标签 # 嵌套标签 +``` + +在 frontmatter 中声明标签: +```yaml +tags: + - 项目管理 + - 知识管理/PKM +``` + +### 注释 + +```markdown +%%这是 Obsidian 注释,不会在预览模式中显示%% + +%% +多行注释 +也是可以的 +%% +``` + +### 数学公式 + +```markdown +行内公式:$E = mc^2$ + +块级公式: +$$ +\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2} +$$ +``` + +### Mermaid 图表 + +````markdown +```mermaid +graph TD + A[开始] --> B{判断} + B -->|是| C[执行] + B -->|否| D[结束] +``` +```` + +--- + +## YAML Frontmatter Properties + +每条笔记应以 YAML frontmatter 开头,定义结构化元数据。 + +### 标准属性 + +```yaml +--- +title: 笔记标题 +aliases: + - 别名1 + - 别名2 +tags: + - 标签1 + - 父标签/子标签 +date: 2026-03-01 +created: 2026-03-01T10:30:00 +modified: 2026-03-01T14:20:00 +author: 作者名 +status: draft | in-progress | reviewed | published +type: note | moc | reference | project | daily +cssclasses: + - custom-class +publish: true +--- +``` + +### 自定义属性(面向 Dataview) + +根据笔记类型添加自定义字段,供 Dataview 查询使用: + +```yaml +--- +# 读书笔记 +book_title: "深度工作" +book_author: "Cal Newport" +rating: 4 +started: 2026-01-15 +finished: 2026-02-20 +category: 生产力 +--- +``` + +```yaml +--- +# 项目笔记 +project: OpenAkita +priority: high +deadline: 2026-06-30 +stakeholders: + - Alice + - Bob +--- +``` + +```yaml +--- +# 会议笔记 +meeting_type: standup | review | planning +participants: + - 张三 + - 李四 +decisions: + - 决策内容 +action_items: + - "[ ] 待办事项" +--- +``` + +### 属性类型 + +Obsidian 支持以下 property 类型: +- **Text**: 普通文本 +- **List**: 数组值 +- **Number**: 数值 +- **Checkbox**: `true`/`false` +- **Date**: `YYYY-MM-DD` +- **Date & time**: `YYYY-MM-DDTHH:mm:ss` +- **Aliases**: 别名列表(内置) +- **Tags**: 标签列表(内置) + +--- + +## 文件夹结构与命名规范 + +### 推荐的 Vault 结构 + +``` +MyVault/ +├── 00 - Inbox/ # 快速捕获,待整理 +├── 01 - Projects/ # 活跃项目 +│ ├── ProjectA/ +│ └── ProjectB/ +├── 02 - Areas/ # 持续关注的领域 +│ ├── 健康/ +│ ├── 财务/ +│ └── 职业发展/ +├── 03 - Resources/ # 参考资料 +│ ├── 读书笔记/ +│ ├── 文章剪藏/ +│ └── 课程笔记/ +├── 04 - Archive/ # 已完成/不活跃 +├── 05 - Templates/ # 模板 +├── 06 - Daily Notes/ # 日记 +├── 07 - MOCs/ # Maps of Content +├── Attachments/ # 附件(图片、PDF 等) +└── Canvas/ # Canvas 文件 +``` + +### 文件命名规范 + +| 类型 | 命名格式 | 示例 | +|------|---------|------| +| 普通笔记 | 描述性名称 | `原子笔记方法论.md` | +| 日记 | `YYYY-MM-DD` | `2026-03-01.md` | +| 会议笔记 | `YYYY-MM-DD 会议主题` | `2026-03-01 产品评审会.md` | +| MOC | `MOC - 主题` | `MOC - 知识管理.md` | +| 模板 | `Template - 类型` | `Template - 读书笔记.md` | +| 项目主页 | `项目名 - Home` | `OpenAkita - Home.md` | + +**命名原则:** +- 避免特殊字符:`/ \ : * ? " < > |` +- 使用空格而非下划线(Obsidian 对空格友好) +- 名称应具有自描述性,无需借助文件夹路径理解含义 + +--- + +## MOC(Maps of Content) + +MOC 是连接相关笔记的导航枢纽,起到"目录"和"思维地图"的作用。 + +### MOC 模板 + +```markdown +--- +title: MOC - 知识管理 +type: moc +tags: + - MOC + - 知识管理 +date: 2026-03-01 +--- + +# 知识管理 + +> [!abstract] 概述 +> 关于个人知识管理(PKM)的核心概念、方法论和工具。 + +## 核心概念 + +- [[卡片盒笔记法]] +- [[原子笔记]] +- [[渐进式总结]] +- [[常青笔记]] + +## 方法论 + +- [[PARA 方法]] +- [[Zettelkasten 方法]] +- [[Building a Second Brain]] +- [[CODE 方法]] + +## 工具与实践 + +- [[Obsidian 使用技巧]] +- [[Dataview 查询食谱]] +- [[模板系统设计]] + +## 相关 MOC + +- [[MOC - 生产力]] +- [[MOC - 学习方法]] +- [[MOC - 写作]] +``` + +### MOC 最佳实践 + +1. **层级结构** — MOC 可以嵌套,顶层 MOC 链接子主题 MOC +2. **动态更新** — 新建笔记后检查是否需要加入相关 MOC +3. **分类灵活** — 同一笔记可出现在多个 MOC 中 +4. **简要注释** — 每个链接可附加一行说明,解释与当前主题的关系 + +--- + +## Dataview 兼容性 + +确保笔记的 frontmatter 属性与 Dataview 查询兼容。 + +### 常用 Dataview 查询模式 + +**表格查询:** +````markdown +```dataview +TABLE rating, book_author, finished +FROM "03 - Resources/读书笔记" +WHERE rating >= 4 +SORT finished DESC +``` +```` + +**列表查询:** +````markdown +```dataview +LIST +FROM #项目管理 AND -"04 - Archive" +WHERE status = "in-progress" +SORT priority ASC +``` +```` + +**任务查询:** +````markdown +```dataview +TASK +FROM "01 - Projects" +WHERE !completed +GROUP BY file.link +``` +```` + +**行内查询:** +```markdown +今天是 `= date(today)`,本库共有 `= length(file.lists)` 条列表项。 +``` + +### Dataview 友好的属性设计 + +- 使用英文属性名(中文属性名在某些查询中可能出问题) +- 日期使用 `YYYY-MM-DD` 格式 +- 布尔值使用 `true`/`false` +- 列表属性使用 YAML 数组语法 + +--- + +## Canvas 支持 + +Obsidian Canvas 是可视化组织笔记关系的画布工具。 + +### Canvas 文件格式 + +Canvas 文件为 `.canvas` 后缀的 JSON 文件,包含节点(nodes)和边(edges)。 + +```json +{ + "nodes": [ + { + "id": "node1", + "type": "text", + "text": "核心概念", + "x": 0, "y": 0, + "width": 250, "height": 60 + }, + { + "id": "node2", + "type": "file", + "file": "03 - Resources/原子笔记.md", + "x": 300, "y": 0, + "width": 250, "height": 60 + } + ], + "edges": [ + { + "id": "edge1", + "fromNode": "node1", + "toNode": "node2", + "label": "包含" + } + ] +} +``` + +### Canvas 节点类型 + +| 类型 | 说明 | 关键属性 | +|------|------|---------| +| `text` | 纯文本卡片 | `text` | +| `file` | 链接到 Vault 中的文件 | `file` | +| `link` | 嵌入网页 | `url` | +| `group` | 分组容器 | `label` | + +### 创建 Canvas 时的注意事项 + +- 节点坐标以画布中心为原点 +- 建议节点宽度 200–400px +- 使用 `group` 节点对相关卡片分组 +- 边可以包含 `label` 描述关系 + +--- + +## Bases 支持 + +Obsidian Bases 是 Obsidian 1.8+ 引入的内置数据库视图功能。 + +### Bases 概述 + +- Bases 文件以 `.base` 为后缀,存储在 Vault 中 +- 自动从笔记的 frontmatter properties 提取结构化数据 +- 支持表格视图、筛选、排序、分组 +- 无需 Dataview 插件即可实现结构化查询 + +### 创建 Bases 时的建议 + +1. **统一属性** — 同一类型的笔记使用相同的 frontmatter 属性集 +2. **属性类型** — 在 Obsidian 设置中预定义属性类型,确保数据一致性 +3. **筛选条件** — 使用文件夹或标签限定数据来源 +4. **视图配置** — 选择合适的列、排序和分组方式 + +--- + +## 笔记模板 + +### 日记模板 + +```markdown +--- +title: "{{date:YYYY-MM-DD}}" +type: daily +date: {{date:YYYY-MM-DD}} +tags: + - daily +--- + +# {{date:YYYY-MM-DD dddd}} + +## 今日计划 +- [ ] + +## 笔记与想法 + + +## 今日回顾 + +### 完成了什么 + + +### 明天的重点 + +``` + +### 读书笔记模板 + +```markdown +--- +title: "{{title}}" +type: reference +book_title: "" +book_author: "" +category: "" +rating: +started: {{date:YYYY-MM-DD}} +finished: +status: in-progress +tags: + - 读书笔记 +--- + +# {{title}} + +> [!info] 书籍信息 +> - **作者**: +> - **出版年份**: +> - **ISBN**: + +## 核心观点 + + +## 章节笔记 + +### 第一章 + + +## 关键引用 + +> + +## 我的思考 + + +## 行动项 +- [ ] + +## 相关笔记 +- [[]] +``` + +### 项目笔记模板 + +```markdown +--- +title: "{{title}}" +type: project +project: "" +status: active +priority: medium +deadline: +stakeholders: [] +tags: + - 项目 +--- + +# {{title}} + +> [!abstract] 项目概述 +> + +## 目标 + + +## 里程碑 + +| 里程碑 | 截止日期 | 状态 | +|--------|---------|------| +| | | 🔴 | + +## 任务 +- [ ] + +## 会议记录 +- [[]] + +## 参考资料 +- [[]] + +## 复盘笔记 + +``` + +--- + +## 工作流程 + +### 创建笔记的标准流程 + +1. **询问保存位置** — 始终先确认用户期望的文件夹路径 +2. **选择或创建模板** — 根据笔记类型使用对应模板 +3. **填写 frontmatter** — 确保所有必需属性完整 +4. **编写内容** — 使用 OFM 语法 +5. **建立链接** — 添加 wikilinks 连接相关笔记 +6. **更新 MOC** — 如有对应 MOC,将新笔记加入其中 + +### 整理 Inbox 的流程 + +1. 浏览 `00 - Inbox/` 中的笔记 +2. 为每条笔记添加或完善 frontmatter +3. 移动到合适的文件夹 +4. 建立与现有笔记的链接 +5. 更新相关 MOC + +### 重构知识库 + +1. 识别孤立笔记(无入链和出链) +2. 合并重复概念 +3. 拆分过长的笔记为原子笔记 +4. 更新失效链接 +5. 归档不活跃内容到 `04 - Archive/` + +--- + +## 注意事项 + +- **不要自行决定保存路径** — 永远先问用户 +- **保持笔记原子性** — 一条笔记一个核心概念 +- **优先使用 wikilinks** — 而非标准 Markdown 链接 +- **YAML frontmatter 必须是文件第一行** — 前面不能有空行 +- **属性名使用英文** — 确保 Dataview 和 Bases 兼容 +- **图片等附件放在专用文件夹** — 如 `Attachments/` +- **定期维护链接** — 重命名笔记后检查链接是否自动更新 +- **备份 Vault** — 建议使用 Git 或 Obsidian Sync diff --git a/account/admin/skills/pdf/LICENSE.txt b/account/admin/skills/pdf/LICENSE.txt new file mode 100644 index 0000000..c55ab42 --- /dev/null +++ b/account/admin/skills/pdf/LICENSE.txt @@ -0,0 +1,30 @@ +© 2025 Anthropic, PBC. All rights reserved. + +LICENSE: Use of these materials (including all code, prompts, assets, files, +and other components of this Skill) is governed by your agreement with +Anthropic regarding use of Anthropic's services. If no separate agreement +exists, use is governed by Anthropic's Consumer Terms of Service or +Commercial Terms of Service, as applicable: +https://www.anthropic.com/legal/consumer-terms +https://www.anthropic.com/legal/commercial-terms +Your applicable agreement is referred to as the "Agreement." "Services" are +as defined in the Agreement. + +ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the +contrary, users may not: + +- Extract these materials from the Services or retain copies of these + materials outside the Services +- Reproduce or copy these materials, except for temporary copies created + automatically during authorized use of the Services +- Create derivative works based on these materials +- Distribute, sublicense, or transfer these materials to any third party +- Make, offer to sell, sell, or import any inventions embodied in these + materials +- Reverse engineer, decompile, or disassemble these materials + +The receipt, viewing, or possession of these materials does not convey or +imply any license or right beyond those expressly granted above. + +Anthropic retains all right, title, and interest in these materials, +including all copyrights, patents, and other intellectual property rights. diff --git a/account/admin/skills/pdf/SKILL.md b/account/admin/skills/pdf/SKILL.md new file mode 100644 index 0000000..d6ef047 --- /dev/null +++ b/account/admin/skills/pdf/SKILL.md @@ -0,0 +1,314 @@ +--- +name: openakita/skills@pdf +description: Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill. +license: Proprietary. LICENSE.txt has complete terms +--- + +# PDF Processing Guide + +## Overview + +This guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see REFERENCE.md. If you need to fill out a PDF form, read FORMS.md and follow its instructions. + +## Quick Start + +```python +from pypdf import PdfReader, PdfWriter + +# Read a PDF +reader = PdfReader("document.pdf") +print(f"Pages: {len(reader.pages)}") + +# Extract text +text = "" +for page in reader.pages: + text += page.extract_text() +``` + +## Python Libraries + +### pypdf - Basic Operations + +#### Merge PDFs +```python +from pypdf import PdfWriter, PdfReader + +writer = PdfWriter() +for pdf_file in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]: + reader = PdfReader(pdf_file) + for page in reader.pages: + writer.add_page(page) + +with open("merged.pdf", "wb") as output: + writer.write(output) +``` + +#### Split PDF +```python +reader = PdfReader("input.pdf") +for i, page in enumerate(reader.pages): + writer = PdfWriter() + writer.add_page(page) + with open(f"page_{i+1}.pdf", "wb") as output: + writer.write(output) +``` + +#### Extract Metadata +```python +reader = PdfReader("document.pdf") +meta = reader.metadata +print(f"Title: {meta.title}") +print(f"Author: {meta.author}") +print(f"Subject: {meta.subject}") +print(f"Creator: {meta.creator}") +``` + +#### Rotate Pages +```python +reader = PdfReader("input.pdf") +writer = PdfWriter() + +page = reader.pages[0] +page.rotate(90) # Rotate 90 degrees clockwise +writer.add_page(page) + +with open("rotated.pdf", "wb") as output: + writer.write(output) +``` + +### pdfplumber - Text and Table Extraction + +#### Extract Text with Layout +```python +import pdfplumber + +with pdfplumber.open("document.pdf") as pdf: + for page in pdf.pages: + text = page.extract_text() + print(text) +``` + +#### Extract Tables +```python +with pdfplumber.open("document.pdf") as pdf: + for i, page in enumerate(pdf.pages): + tables = page.extract_tables() + for j, table in enumerate(tables): + print(f"Table {j+1} on page {i+1}:") + for row in table: + print(row) +``` + +#### Advanced Table Extraction +```python +import pandas as pd + +with pdfplumber.open("document.pdf") as pdf: + all_tables = [] + for page in pdf.pages: + tables = page.extract_tables() + for table in tables: + if table: # Check if table is not empty + df = pd.DataFrame(table[1:], columns=table[0]) + all_tables.append(df) + +# Combine all tables +if all_tables: + combined_df = pd.concat(all_tables, ignore_index=True) + combined_df.to_excel("extracted_tables.xlsx", index=False) +``` + +### reportlab - Create PDFs + +#### Basic PDF Creation +```python +from reportlab.lib.pagesizes import letter +from reportlab.pdfgen import canvas + +c = canvas.Canvas("hello.pdf", pagesize=letter) +width, height = letter + +# Add text +c.drawString(100, height - 100, "Hello World!") +c.drawString(100, height - 120, "This is a PDF created with reportlab") + +# Add a line +c.line(100, height - 140, 400, height - 140) + +# Save +c.save() +``` + +#### Create PDF with Multiple Pages +```python +from reportlab.lib.pagesizes import letter +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak +from reportlab.lib.styles import getSampleStyleSheet + +doc = SimpleDocTemplate("report.pdf", pagesize=letter) +styles = getSampleStyleSheet() +story = [] + +# Add content +title = Paragraph("Report Title", styles['Title']) +story.append(title) +story.append(Spacer(1, 12)) + +body = Paragraph("This is the body of the report. " * 20, styles['Normal']) +story.append(body) +story.append(PageBreak()) + +# Page 2 +story.append(Paragraph("Page 2", styles['Heading1'])) +story.append(Paragraph("Content for page 2", styles['Normal'])) + +# Build PDF +doc.build(story) +``` + +#### Subscripts and Superscripts + +**IMPORTANT**: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes. + +Instead, use ReportLab's XML markup tags in Paragraph objects: +```python +from reportlab.platypus import Paragraph +from reportlab.lib.styles import getSampleStyleSheet + +styles = getSampleStyleSheet() + +# Subscripts: use tag +chemical = Paragraph("H2O", styles['Normal']) + +# Superscripts: use tag +squared = Paragraph("x2 + y2", styles['Normal']) +``` + +For canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts. + +## Command-Line Tools + +### pdftotext (poppler-utils) +```bash +# Extract text +pdftotext input.pdf output.txt + +# Extract text preserving layout +pdftotext -layout input.pdf output.txt + +# Extract specific pages +pdftotext -f 1 -l 5 input.pdf output.txt # Pages 1-5 +``` + +### qpdf +```bash +# Merge PDFs +qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf + +# Split pages +qpdf input.pdf --pages . 1-5 -- pages1-5.pdf +qpdf input.pdf --pages . 6-10 -- pages6-10.pdf + +# Rotate pages +qpdf input.pdf output.pdf --rotate=+90:1 # Rotate page 1 by 90 degrees + +# Remove password +qpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf +``` + +### pdftk (if available) +```bash +# Merge +pdftk file1.pdf file2.pdf cat output merged.pdf + +# Split +pdftk input.pdf burst + +# Rotate +pdftk input.pdf rotate 1east output rotated.pdf +``` + +## Common Tasks + +### Extract Text from Scanned PDFs +```python +# Requires: pip install pytesseract pdf2image +import pytesseract +from pdf2image import convert_from_path + +# Convert PDF to images +images = convert_from_path('scanned.pdf') + +# OCR each page +text = "" +for i, image in enumerate(images): + text += f"Page {i+1}:\n" + text += pytesseract.image_to_string(image) + text += "\n\n" + +print(text) +``` + +### Add Watermark +```python +from pypdf import PdfReader, PdfWriter + +# Create watermark (or load existing) +watermark = PdfReader("watermark.pdf").pages[0] + +# Apply to all pages +reader = PdfReader("document.pdf") +writer = PdfWriter() + +for page in reader.pages: + page.merge_page(watermark) + writer.add_page(page) + +with open("watermarked.pdf", "wb") as output: + writer.write(output) +``` + +### Extract Images +```bash +# Using pdfimages (poppler-utils) +pdfimages -j input.pdf output_prefix + +# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc. +``` + +### Password Protection +```python +from pypdf import PdfReader, PdfWriter + +reader = PdfReader("input.pdf") +writer = PdfWriter() + +for page in reader.pages: + writer.add_page(page) + +# Add password +writer.encrypt("userpassword", "ownerpassword") + +with open("encrypted.pdf", "wb") as output: + writer.write(output) +``` + +## Quick Reference + +| Task | Best Tool | Command/Code | +|------|-----------|--------------| +| Merge PDFs | pypdf | `writer.add_page(page)` | +| Split PDFs | pypdf | One page per file | +| Extract text | pdfplumber | `page.extract_text()` | +| Extract tables | pdfplumber | `page.extract_tables()` | +| Create PDFs | reportlab | Canvas or Platypus | +| Command line merge | qpdf | `qpdf --empty --pages ...` | +| OCR scanned PDFs | pytesseract | Convert to image first | +| Fill PDF forms | pdf-lib or pypdf (see FORMS.md) | See FORMS.md | + +## Next Steps + +- For advanced pypdfium2 usage, see REFERENCE.md +- For JavaScript libraries (pdf-lib), see REFERENCE.md +- If you need to fill out a PDF form, follow the instructions in FORMS.md +- For troubleshooting guides, see REFERENCE.md diff --git a/account/admin/skills/pdf/forms.md b/account/admin/skills/pdf/forms.md new file mode 100644 index 0000000..6e7e1e0 --- /dev/null +++ b/account/admin/skills/pdf/forms.md @@ -0,0 +1,294 @@ +**CRITICAL: You MUST complete these steps in order. Do not skip ahead to writing code.** + +If you need to fill out a PDF form, first check to see if the PDF has fillable form fields. Run this script from this file's directory: + `python scripts/check_fillable_fields `, and depending on the result go to either the "Fillable fields" or "Non-fillable fields" and follow those instructions. + +# Fillable fields +If the PDF has fillable form fields: +- Run this script from this file's directory: `python scripts/extract_form_field_info.py `. It will create a JSON file with a list of fields in this format: +``` +[ + { + "field_id": (unique ID for the field), + "page": (page number, 1-based), + "rect": ([left, bottom, right, top] bounding box in PDF coordinates, y=0 is the bottom of the page), + "type": ("text", "checkbox", "radio_group", or "choice"), + }, + // Checkboxes have "checked_value" and "unchecked_value" properties: + { + "field_id": (unique ID for the field), + "page": (page number, 1-based), + "type": "checkbox", + "checked_value": (Set the field to this value to check the checkbox), + "unchecked_value": (Set the field to this value to uncheck the checkbox), + }, + // Radio groups have a "radio_options" list with the possible choices. + { + "field_id": (unique ID for the field), + "page": (page number, 1-based), + "type": "radio_group", + "radio_options": [ + { + "value": (set the field to this value to select this radio option), + "rect": (bounding box for the radio button for this option) + }, + // Other radio options + ] + }, + // Multiple choice fields have a "choice_options" list with the possible choices: + { + "field_id": (unique ID for the field), + "page": (page number, 1-based), + "type": "choice", + "choice_options": [ + { + "value": (set the field to this value to select this option), + "text": (display text of the option) + }, + // Other choice options + ], + } +] +``` +- Convert the PDF to PNGs (one image for each page) with this script (run from this file's directory): +`python scripts/convert_pdf_to_images.py ` +Then analyze the images to determine the purpose of each form field (make sure to convert the bounding box PDF coordinates to image coordinates). +- Create a `field_values.json` file in this format with the values to be entered for each field: +``` +[ + { + "field_id": "last_name", // Must match the field_id from `extract_form_field_info.py` + "description": "The user's last name", + "page": 1, // Must match the "page" value in field_info.json + "value": "Simpson" + }, + { + "field_id": "Checkbox12", + "description": "Checkbox to be checked if the user is 18 or over", + "page": 1, + "value": "/On" // If this is a checkbox, use its "checked_value" value to check it. If it's a radio button group, use one of the "value" values in "radio_options". + }, + // more fields +] +``` +- Run the `fill_fillable_fields.py` script from this file's directory to create a filled-in PDF: +`python scripts/fill_fillable_fields.py ` +This script will verify that the field IDs and values you provide are valid; if it prints error messages, correct the appropriate fields and try again. + +# Non-fillable fields +If the PDF doesn't have fillable form fields, you'll add text annotations. First try to extract coordinates from the PDF structure (more accurate), then fall back to visual estimation if needed. + +## Step 1: Try Structure Extraction First + +Run this script to extract text labels, lines, and checkboxes with their exact PDF coordinates: +`python scripts/extract_form_structure.py form_structure.json` + +This creates a JSON file containing: +- **labels**: Every text element with exact coordinates (x0, top, x1, bottom in PDF points) +- **lines**: Horizontal lines that define row boundaries +- **checkboxes**: Small square rectangles that are checkboxes (with center coordinates) +- **row_boundaries**: Row top/bottom positions calculated from horizontal lines + +**Check the results**: If `form_structure.json` has meaningful labels (text elements that correspond to form fields), use **Approach A: Structure-Based Coordinates**. If the PDF is scanned/image-based and has few or no labels, use **Approach B: Visual Estimation**. + +--- + +## Approach A: Structure-Based Coordinates (Preferred) + +Use this when `extract_form_structure.py` found text labels in the PDF. + +### A.1: Analyze the Structure + +Read form_structure.json and identify: + +1. **Label groups**: Adjacent text elements that form a single label (e.g., "Last" + "Name") +2. **Row structure**: Labels with similar `top` values are in the same row +3. **Field columns**: Entry areas start after label ends (x0 = label.x1 + gap) +4. **Checkboxes**: Use the checkbox coordinates directly from the structure + +**Coordinate system**: PDF coordinates where y=0 is at TOP of page, y increases downward. + +### A.2: Check for Missing Elements + +The structure extraction may not detect all form elements. Common cases: +- **Circular checkboxes**: Only square rectangles are detected as checkboxes +- **Complex graphics**: Decorative elements or non-standard form controls +- **Faded or light-colored elements**: May not be extracted + +If you see form fields in the PDF images that aren't in form_structure.json, you'll need to use **visual analysis** for those specific fields (see "Hybrid Approach" below). + +### A.3: Create fields.json with PDF Coordinates + +For each field, calculate entry coordinates from the extracted structure: + +**Text fields:** +- entry x0 = label x1 + 5 (small gap after label) +- entry x1 = next label's x0, or row boundary +- entry top = same as label top +- entry bottom = row boundary line below, or label bottom + row_height + +**Checkboxes:** +- Use the checkbox rectangle coordinates directly from form_structure.json +- entry_bounding_box = [checkbox.x0, checkbox.top, checkbox.x1, checkbox.bottom] + +Create fields.json using `pdf_width` and `pdf_height` (signals PDF coordinates): +```json +{ + "pages": [ + {"page_number": 1, "pdf_width": 612, "pdf_height": 792} + ], + "form_fields": [ + { + "page_number": 1, + "description": "Last name entry field", + "field_label": "Last Name", + "label_bounding_box": [43, 63, 87, 73], + "entry_bounding_box": [92, 63, 260, 79], + "entry_text": {"text": "Smith", "font_size": 10} + }, + { + "page_number": 1, + "description": "US Citizen Yes checkbox", + "field_label": "Yes", + "label_bounding_box": [260, 200, 280, 210], + "entry_bounding_box": [285, 197, 292, 205], + "entry_text": {"text": "X"} + } + ] +} +``` + +**Important**: Use `pdf_width`/`pdf_height` and coordinates directly from form_structure.json. + +### A.4: Validate Bounding Boxes + +Before filling, check your bounding boxes for errors: +`python scripts/check_bounding_boxes.py fields.json` + +This checks for intersecting bounding boxes and entry boxes that are too small for the font size. Fix any reported errors before filling. + +--- + +## Approach B: Visual Estimation (Fallback) + +Use this when the PDF is scanned/image-based and structure extraction found no usable text labels (e.g., all text shows as "(cid:X)" patterns). + +### B.1: Convert PDF to Images + +`python scripts/convert_pdf_to_images.py ` + +### B.2: Initial Field Identification + +Examine each page image to identify form sections and get **rough estimates** of field locations: +- Form field labels and their approximate positions +- Entry areas (lines, boxes, or blank spaces for text input) +- Checkboxes and their approximate locations + +For each field, note approximate pixel coordinates (they don't need to be precise yet). + +### B.3: Zoom Refinement (CRITICAL for accuracy) + +For each field, crop a region around the estimated position to refine coordinates precisely. + +**Create a zoomed crop using ImageMagick:** +```bash +magick -crop x++ +repage +``` + +Where: +- `, ` = top-left corner of crop region (use your rough estimate minus padding) +- `, ` = size of crop region (field area plus ~50px padding on each side) + +**Example:** To refine a "Name" field estimated around (100, 150): +```bash +magick images_dir/page_1.png -crop 300x80+50+120 +repage crops/name_field.png +``` + +(Note: if the `magick` command isn't available, try `convert` with the same arguments). + +**Examine the cropped image** to determine precise coordinates: +1. Identify the exact pixel where the entry area begins (after the label) +2. Identify where the entry area ends (before next field or edge) +3. Identify the top and bottom of the entry line/box + +**Convert crop coordinates back to full image coordinates:** +- full_x = crop_x + crop_offset_x +- full_y = crop_y + crop_offset_y + +Example: If the crop started at (50, 120) and the entry box starts at (52, 18) within the crop: +- entry_x0 = 52 + 50 = 102 +- entry_top = 18 + 120 = 138 + +**Repeat for each field**, grouping nearby fields into single crops when possible. + +### B.4: Create fields.json with Refined Coordinates + +Create fields.json using `image_width` and `image_height` (signals image coordinates): +```json +{ + "pages": [ + {"page_number": 1, "image_width": 1700, "image_height": 2200} + ], + "form_fields": [ + { + "page_number": 1, + "description": "Last name entry field", + "field_label": "Last Name", + "label_bounding_box": [120, 175, 242, 198], + "entry_bounding_box": [255, 175, 720, 218], + "entry_text": {"text": "Smith", "font_size": 10} + } + ] +} +``` + +**Important**: Use `image_width`/`image_height` and the refined pixel coordinates from the zoom analysis. + +### B.5: Validate Bounding Boxes + +Before filling, check your bounding boxes for errors: +`python scripts/check_bounding_boxes.py fields.json` + +This checks for intersecting bounding boxes and entry boxes that are too small for the font size. Fix any reported errors before filling. + +--- + +## Hybrid Approach: Structure + Visual + +Use this when structure extraction works for most fields but misses some elements (e.g., circular checkboxes, unusual form controls). + +1. **Use Approach A** for fields that were detected in form_structure.json +2. **Convert PDF to images** for visual analysis of missing fields +3. **Use zoom refinement** (from Approach B) for the missing fields +4. **Combine coordinates**: For fields from structure extraction, use `pdf_width`/`pdf_height`. For visually-estimated fields, you must convert image coordinates to PDF coordinates: + - pdf_x = image_x * (pdf_width / image_width) + - pdf_y = image_y * (pdf_height / image_height) +5. **Use a single coordinate system** in fields.json - convert all to PDF coordinates with `pdf_width`/`pdf_height` + +--- + +## Step 2: Validate Before Filling + +**Always validate bounding boxes before filling:** +`python scripts/check_bounding_boxes.py fields.json` + +This checks for: +- Intersecting bounding boxes (which would cause overlapping text) +- Entry boxes that are too small for the specified font size + +Fix any reported errors in fields.json before proceeding. + +## Step 3: Fill the Form + +The fill script auto-detects the coordinate system and handles conversion: +`python scripts/fill_pdf_form_with_annotations.py fields.json ` + +## Step 4: Verify Output + +Convert the filled PDF to images and verify text placement: +`python scripts/convert_pdf_to_images.py ` + +If text is mispositioned: +- **Approach A**: Check that you're using PDF coordinates from form_structure.json with `pdf_width`/`pdf_height` +- **Approach B**: Check that image dimensions match and coordinates are accurate pixels +- **Hybrid**: Ensure coordinate conversions are correct for visually-estimated fields diff --git a/account/admin/skills/pdf/reference.md b/account/admin/skills/pdf/reference.md new file mode 100644 index 0000000..41400bf --- /dev/null +++ b/account/admin/skills/pdf/reference.md @@ -0,0 +1,612 @@ +# PDF Processing Advanced Reference + +This document contains advanced PDF processing features, detailed examples, and additional libraries not covered in the main skill instructions. + +## pypdfium2 Library (Apache/BSD License) + +### Overview +pypdfium2 is a Python binding for PDFium (Chromium's PDF library). It's excellent for fast PDF rendering, image generation, and serves as a PyMuPDF replacement. + +### Render PDF to Images +```python +import pypdfium2 as pdfium +from PIL import Image + +# Load PDF +pdf = pdfium.PdfDocument("document.pdf") + +# Render page to image +page = pdf[0] # First page +bitmap = page.render( + scale=2.0, # Higher resolution + rotation=0 # No rotation +) + +# Convert to PIL Image +img = bitmap.to_pil() +img.save("page_1.png", "PNG") + +# Process multiple pages +for i, page in enumerate(pdf): + bitmap = page.render(scale=1.5) + img = bitmap.to_pil() + img.save(f"page_{i+1}.jpg", "JPEG", quality=90) +``` + +### Extract Text with pypdfium2 +```python +import pypdfium2 as pdfium + +pdf = pdfium.PdfDocument("document.pdf") +for i, page in enumerate(pdf): + text = page.get_text() + print(f"Page {i+1} text length: {len(text)} chars") +``` + +## JavaScript Libraries + +### pdf-lib (MIT License) + +pdf-lib is a powerful JavaScript library for creating and modifying PDF documents in any JavaScript environment. + +#### Load and Manipulate Existing PDF +```javascript +import { PDFDocument } from 'pdf-lib'; +import fs from 'fs'; + +async function manipulatePDF() { + // Load existing PDF + const existingPdfBytes = fs.readFileSync('input.pdf'); + const pdfDoc = await PDFDocument.load(existingPdfBytes); + + // Get page count + const pageCount = pdfDoc.getPageCount(); + console.log(`Document has ${pageCount} pages`); + + // Add new page + const newPage = pdfDoc.addPage([600, 400]); + newPage.drawText('Added by pdf-lib', { + x: 100, + y: 300, + size: 16 + }); + + // Save modified PDF + const pdfBytes = await pdfDoc.save(); + fs.writeFileSync('modified.pdf', pdfBytes); +} +``` + +#### Create Complex PDFs from Scratch +```javascript +import { PDFDocument, rgb, StandardFonts } from 'pdf-lib'; +import fs from 'fs'; + +async function createPDF() { + const pdfDoc = await PDFDocument.create(); + + // Add fonts + const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica); + const helveticaBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold); + + // Add page + const page = pdfDoc.addPage([595, 842]); // A4 size + const { width, height } = page.getSize(); + + // Add text with styling + page.drawText('Invoice #12345', { + x: 50, + y: height - 50, + size: 18, + font: helveticaBold, + color: rgb(0.2, 0.2, 0.8) + }); + + // Add rectangle (header background) + page.drawRectangle({ + x: 40, + y: height - 100, + width: width - 80, + height: 30, + color: rgb(0.9, 0.9, 0.9) + }); + + // Add table-like content + const items = [ + ['Item', 'Qty', 'Price', 'Total'], + ['Widget', '2', '$50', '$100'], + ['Gadget', '1', '$75', '$75'] + ]; + + let yPos = height - 150; + items.forEach(row => { + let xPos = 50; + row.forEach(cell => { + page.drawText(cell, { + x: xPos, + y: yPos, + size: 12, + font: helveticaFont + }); + xPos += 120; + }); + yPos -= 25; + }); + + const pdfBytes = await pdfDoc.save(); + fs.writeFileSync('created.pdf', pdfBytes); +} +``` + +#### Advanced Merge and Split Operations +```javascript +import { PDFDocument } from 'pdf-lib'; +import fs from 'fs'; + +async function mergePDFs() { + // Create new document + const mergedPdf = await PDFDocument.create(); + + // Load source PDFs + const pdf1Bytes = fs.readFileSync('doc1.pdf'); + const pdf2Bytes = fs.readFileSync('doc2.pdf'); + + const pdf1 = await PDFDocument.load(pdf1Bytes); + const pdf2 = await PDFDocument.load(pdf2Bytes); + + // Copy pages from first PDF + const pdf1Pages = await mergedPdf.copyPages(pdf1, pdf1.getPageIndices()); + pdf1Pages.forEach(page => mergedPdf.addPage(page)); + + // Copy specific pages from second PDF (pages 0, 2, 4) + const pdf2Pages = await mergedPdf.copyPages(pdf2, [0, 2, 4]); + pdf2Pages.forEach(page => mergedPdf.addPage(page)); + + const mergedPdfBytes = await mergedPdf.save(); + fs.writeFileSync('merged.pdf', mergedPdfBytes); +} +``` + +### pdfjs-dist (Apache License) + +PDF.js is Mozilla's JavaScript library for rendering PDFs in the browser. + +#### Basic PDF Loading and Rendering +```javascript +import * as pdfjsLib from 'pdfjs-dist'; + +// Configure worker (important for performance) +pdfjsLib.GlobalWorkerOptions.workerSrc = './pdf.worker.js'; + +async function renderPDF() { + // Load PDF + const loadingTask = pdfjsLib.getDocument('document.pdf'); + const pdf = await loadingTask.promise; + + console.log(`Loaded PDF with ${pdf.numPages} pages`); + + // Get first page + const page = await pdf.getPage(1); + const viewport = page.getViewport({ scale: 1.5 }); + + // Render to canvas + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + canvas.height = viewport.height; + canvas.width = viewport.width; + + const renderContext = { + canvasContext: context, + viewport: viewport + }; + + await page.render(renderContext).promise; + document.body.appendChild(canvas); +} +``` + +#### Extract Text with Coordinates +```javascript +import * as pdfjsLib from 'pdfjs-dist'; + +async function extractText() { + const loadingTask = pdfjsLib.getDocument('document.pdf'); + const pdf = await loadingTask.promise; + + let fullText = ''; + + // Extract text from all pages + for (let i = 1; i <= pdf.numPages; i++) { + const page = await pdf.getPage(i); + const textContent = await page.getTextContent(); + + const pageText = textContent.items + .map(item => item.str) + .join(' '); + + fullText += `\n--- Page ${i} ---\n${pageText}`; + + // Get text with coordinates for advanced processing + const textWithCoords = textContent.items.map(item => ({ + text: item.str, + x: item.transform[4], + y: item.transform[5], + width: item.width, + height: item.height + })); + } + + console.log(fullText); + return fullText; +} +``` + +#### Extract Annotations and Forms +```javascript +import * as pdfjsLib from 'pdfjs-dist'; + +async function extractAnnotations() { + const loadingTask = pdfjsLib.getDocument('annotated.pdf'); + const pdf = await loadingTask.promise; + + for (let i = 1; i <= pdf.numPages; i++) { + const page = await pdf.getPage(i); + const annotations = await page.getAnnotations(); + + annotations.forEach(annotation => { + console.log(`Annotation type: ${annotation.subtype}`); + console.log(`Content: ${annotation.contents}`); + console.log(`Coordinates: ${JSON.stringify(annotation.rect)}`); + }); + } +} +``` + +## Advanced Command-Line Operations + +### poppler-utils Advanced Features + +#### Extract Text with Bounding Box Coordinates +```bash +# Extract text with bounding box coordinates (essential for structured data) +pdftotext -bbox-layout document.pdf output.xml + +# The XML output contains precise coordinates for each text element +``` + +#### Advanced Image Conversion +```bash +# Convert to PNG images with specific resolution +pdftoppm -png -r 300 document.pdf output_prefix + +# Convert specific page range with high resolution +pdftoppm -png -r 600 -f 1 -l 3 document.pdf high_res_pages + +# Convert to JPEG with quality setting +pdftoppm -jpeg -jpegopt quality=85 -r 200 document.pdf jpeg_output +``` + +#### Extract Embedded Images +```bash +# Extract all embedded images with metadata +pdfimages -j -p document.pdf page_images + +# List image info without extracting +pdfimages -list document.pdf + +# Extract images in their original format +pdfimages -all document.pdf images/img +``` + +### qpdf Advanced Features + +#### Complex Page Manipulation +```bash +# Split PDF into groups of pages +qpdf --split-pages=3 input.pdf output_group_%02d.pdf + +# Extract specific pages with complex ranges +qpdf input.pdf --pages input.pdf 1,3-5,8,10-end -- extracted.pdf + +# Merge specific pages from multiple PDFs +qpdf --empty --pages doc1.pdf 1-3 doc2.pdf 5-7 doc3.pdf 2,4 -- combined.pdf +``` + +#### PDF Optimization and Repair +```bash +# Optimize PDF for web (linearize for streaming) +qpdf --linearize input.pdf optimized.pdf + +# Remove unused objects and compress +qpdf --optimize-level=all input.pdf compressed.pdf + +# Attempt to repair corrupted PDF structure +qpdf --check input.pdf +qpdf --fix-qdf damaged.pdf repaired.pdf + +# Show detailed PDF structure for debugging +qpdf --show-all-pages input.pdf > structure.txt +``` + +#### Advanced Encryption +```bash +# Add password protection with specific permissions +qpdf --encrypt user_pass owner_pass 256 --print=none --modify=none -- input.pdf encrypted.pdf + +# Check encryption status +qpdf --show-encryption encrypted.pdf + +# Remove password protection (requires password) +qpdf --password=secret123 --decrypt encrypted.pdf decrypted.pdf +``` + +## Advanced Python Techniques + +### pdfplumber Advanced Features + +#### Extract Text with Precise Coordinates +```python +import pdfplumber + +with pdfplumber.open("document.pdf") as pdf: + page = pdf.pages[0] + + # Extract all text with coordinates + chars = page.chars + for char in chars[:10]: # First 10 characters + print(f"Char: '{char['text']}' at x:{char['x0']:.1f} y:{char['y0']:.1f}") + + # Extract text by bounding box (left, top, right, bottom) + bbox_text = page.within_bbox((100, 100, 400, 200)).extract_text() +``` + +#### Advanced Table Extraction with Custom Settings +```python +import pdfplumber +import pandas as pd + +with pdfplumber.open("complex_table.pdf") as pdf: + page = pdf.pages[0] + + # Extract tables with custom settings for complex layouts + table_settings = { + "vertical_strategy": "lines", + "horizontal_strategy": "lines", + "snap_tolerance": 3, + "intersection_tolerance": 15 + } + tables = page.extract_tables(table_settings) + + # Visual debugging for table extraction + img = page.to_image(resolution=150) + img.save("debug_layout.png") +``` + +### reportlab Advanced Features + +#### Create Professional Reports with Tables +```python +from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph +from reportlab.lib.styles import getSampleStyleSheet +from reportlab.lib import colors + +# Sample data +data = [ + ['Product', 'Q1', 'Q2', 'Q3', 'Q4'], + ['Widgets', '120', '135', '142', '158'], + ['Gadgets', '85', '92', '98', '105'] +] + +# Create PDF with table +doc = SimpleDocTemplate("report.pdf") +elements = [] + +# Add title +styles = getSampleStyleSheet() +title = Paragraph("Quarterly Sales Report", styles['Title']) +elements.append(title) + +# Add table with advanced styling +table = Table(data) +table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (-1, 0), colors.grey), + ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), + ('ALIGN', (0, 0), (-1, -1), 'CENTER'), + ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('FONTSIZE', (0, 0), (-1, 0), 14), + ('BOTTOMPADDING', (0, 0), (-1, 0), 12), + ('BACKGROUND', (0, 1), (-1, -1), colors.beige), + ('GRID', (0, 0), (-1, -1), 1, colors.black) +])) +elements.append(table) + +doc.build(elements) +``` + +## Complex Workflows + +### Extract Figures/Images from PDF + +#### Method 1: Using pdfimages (fastest) +```bash +# Extract all images with original quality +pdfimages -all document.pdf images/img +``` + +#### Method 2: Using pypdfium2 + Image Processing +```python +import pypdfium2 as pdfium +from PIL import Image +import numpy as np + +def extract_figures(pdf_path, output_dir): + pdf = pdfium.PdfDocument(pdf_path) + + for page_num, page in enumerate(pdf): + # Render high-resolution page + bitmap = page.render(scale=3.0) + img = bitmap.to_pil() + + # Convert to numpy for processing + img_array = np.array(img) + + # Simple figure detection (non-white regions) + mask = np.any(img_array != [255, 255, 255], axis=2) + + # Find contours and extract bounding boxes + # (This is simplified - real implementation would need more sophisticated detection) + + # Save detected figures + # ... implementation depends on specific needs +``` + +### Batch PDF Processing with Error Handling +```python +import os +import glob +from pypdf import PdfReader, PdfWriter +import logging + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +def batch_process_pdfs(input_dir, operation='merge'): + pdf_files = glob.glob(os.path.join(input_dir, "*.pdf")) + + if operation == 'merge': + writer = PdfWriter() + for pdf_file in pdf_files: + try: + reader = PdfReader(pdf_file) + for page in reader.pages: + writer.add_page(page) + logger.info(f"Processed: {pdf_file}") + except Exception as e: + logger.error(f"Failed to process {pdf_file}: {e}") + continue + + with open("batch_merged.pdf", "wb") as output: + writer.write(output) + + elif operation == 'extract_text': + for pdf_file in pdf_files: + try: + reader = PdfReader(pdf_file) + text = "" + for page in reader.pages: + text += page.extract_text() + + output_file = pdf_file.replace('.pdf', '.txt') + with open(output_file, 'w', encoding='utf-8') as f: + f.write(text) + logger.info(f"Extracted text from: {pdf_file}") + + except Exception as e: + logger.error(f"Failed to extract text from {pdf_file}: {e}") + continue +``` + +### Advanced PDF Cropping +```python +from pypdf import PdfWriter, PdfReader + +reader = PdfReader("input.pdf") +writer = PdfWriter() + +# Crop page (left, bottom, right, top in points) +page = reader.pages[0] +page.mediabox.left = 50 +page.mediabox.bottom = 50 +page.mediabox.right = 550 +page.mediabox.top = 750 + +writer.add_page(page) +with open("cropped.pdf", "wb") as output: + writer.write(output) +``` + +## Performance Optimization Tips + +### 1. For Large PDFs +- Use streaming approaches instead of loading entire PDF in memory +- Use `qpdf --split-pages` for splitting large files +- Process pages individually with pypdfium2 + +### 2. For Text Extraction +- `pdftotext -bbox-layout` is fastest for plain text extraction +- Use pdfplumber for structured data and tables +- Avoid `pypdf.extract_text()` for very large documents + +### 3. For Image Extraction +- `pdfimages` is much faster than rendering pages +- Use low resolution for previews, high resolution for final output + +### 4. For Form Filling +- pdf-lib maintains form structure better than most alternatives +- Pre-validate form fields before processing + +### 5. Memory Management +```python +# Process PDFs in chunks +def process_large_pdf(pdf_path, chunk_size=10): + reader = PdfReader(pdf_path) + total_pages = len(reader.pages) + + for start_idx in range(0, total_pages, chunk_size): + end_idx = min(start_idx + chunk_size, total_pages) + writer = PdfWriter() + + for i in range(start_idx, end_idx): + writer.add_page(reader.pages[i]) + + # Process chunk + with open(f"chunk_{start_idx//chunk_size}.pdf", "wb") as output: + writer.write(output) +``` + +## Troubleshooting Common Issues + +### Encrypted PDFs +```python +# Handle password-protected PDFs +from pypdf import PdfReader + +try: + reader = PdfReader("encrypted.pdf") + if reader.is_encrypted: + reader.decrypt("password") +except Exception as e: + print(f"Failed to decrypt: {e}") +``` + +### Corrupted PDFs +```bash +# Use qpdf to repair +qpdf --check corrupted.pdf +qpdf --replace-input corrupted.pdf +``` + +### Text Extraction Issues +```python +# Fallback to OCR for scanned PDFs +import pytesseract +from pdf2image import convert_from_path + +def extract_text_with_ocr(pdf_path): + images = convert_from_path(pdf_path) + text = "" + for i, image in enumerate(images): + text += pytesseract.image_to_string(image) + return text +``` + +## License Information + +- **pypdf**: BSD License +- **pdfplumber**: MIT License +- **pypdfium2**: Apache/BSD License +- **reportlab**: BSD License +- **poppler-utils**: GPL-2 License +- **qpdf**: Apache License +- **pdf-lib**: MIT License +- **pdfjs-dist**: Apache License \ No newline at end of file diff --git a/account/admin/skills/pdf/scripts/check_bounding_boxes.py b/account/admin/skills/pdf/scripts/check_bounding_boxes.py new file mode 100644 index 0000000..2cc5e34 --- /dev/null +++ b/account/admin/skills/pdf/scripts/check_bounding_boxes.py @@ -0,0 +1,65 @@ +from dataclasses import dataclass +import json +import sys + + + + +@dataclass +class RectAndField: + rect: list[float] + rect_type: str + field: dict + + +def get_bounding_box_messages(fields_json_stream) -> list[str]: + messages = [] + fields = json.load(fields_json_stream) + messages.append(f"Read {len(fields['form_fields'])} fields") + + def rects_intersect(r1, r2): + disjoint_horizontal = r1[0] >= r2[2] or r1[2] <= r2[0] + disjoint_vertical = r1[1] >= r2[3] or r1[3] <= r2[1] + return not (disjoint_horizontal or disjoint_vertical) + + rects_and_fields = [] + for f in fields["form_fields"]: + rects_and_fields.append(RectAndField(f["label_bounding_box"], "label", f)) + rects_and_fields.append(RectAndField(f["entry_bounding_box"], "entry", f)) + + has_error = False + for i, ri in enumerate(rects_and_fields): + for j in range(i + 1, len(rects_and_fields)): + rj = rects_and_fields[j] + if ri.field["page_number"] == rj.field["page_number"] and rects_intersect(ri.rect, rj.rect): + has_error = True + if ri.field is rj.field: + messages.append(f"FAILURE: intersection between label and entry bounding boxes for `{ri.field['description']}` ({ri.rect}, {rj.rect})") + else: + messages.append(f"FAILURE: intersection between {ri.rect_type} bounding box for `{ri.field['description']}` ({ri.rect}) and {rj.rect_type} bounding box for `{rj.field['description']}` ({rj.rect})") + if len(messages) >= 20: + messages.append("Aborting further checks; fix bounding boxes and try again") + return messages + if ri.rect_type == "entry": + if "entry_text" in ri.field: + font_size = ri.field["entry_text"].get("font_size", 14) + entry_height = ri.rect[3] - ri.rect[1] + if entry_height < font_size: + has_error = True + messages.append(f"FAILURE: entry bounding box height ({entry_height}) for `{ri.field['description']}` is too short for the text content (font size: {font_size}). Increase the box height or decrease the font size.") + if len(messages) >= 20: + messages.append("Aborting further checks; fix bounding boxes and try again") + return messages + + if not has_error: + messages.append("SUCCESS: All bounding boxes are valid") + return messages + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: check_bounding_boxes.py [fields.json]") + sys.exit(1) + with open(sys.argv[1]) as f: + messages = get_bounding_box_messages(f) + for msg in messages: + print(msg) diff --git a/account/admin/skills/pdf/scripts/check_bounding_boxes_test.py b/account/admin/skills/pdf/scripts/check_bounding_boxes_test.py new file mode 100644 index 0000000..1dbb463 --- /dev/null +++ b/account/admin/skills/pdf/scripts/check_bounding_boxes_test.py @@ -0,0 +1,226 @@ +import unittest +import json +import io +from check_bounding_boxes import get_bounding_box_messages + + +# Currently this is not run automatically in CI; it's just for documentation and manual checking. +class TestGetBoundingBoxMessages(unittest.TestCase): + + def create_json_stream(self, data): + """Helper to create a JSON stream from data""" + return io.StringIO(json.dumps(data)) + + def test_no_intersections(self): + """Test case with no bounding box intersections""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 30] + }, + { + "description": "Email", + "page_number": 1, + "label_bounding_box": [10, 40, 50, 60], + "entry_bounding_box": [60, 40, 150, 60] + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("SUCCESS" in msg for msg in messages)) + self.assertFalse(any("FAILURE" in msg for msg in messages)) + + def test_label_entry_intersection_same_field(self): + """Test intersection between label and entry of the same field""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 60, 30], + "entry_bounding_box": [50, 10, 150, 30] # Overlaps with label + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages)) + self.assertFalse(any("SUCCESS" in msg for msg in messages)) + + def test_intersection_between_different_fields(self): + """Test intersection between bounding boxes of different fields""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 30] + }, + { + "description": "Email", + "page_number": 1, + "label_bounding_box": [40, 20, 80, 40], # Overlaps with Name's boxes + "entry_bounding_box": [160, 10, 250, 30] + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages)) + self.assertFalse(any("SUCCESS" in msg for msg in messages)) + + def test_different_pages_no_intersection(self): + """Test that boxes on different pages don't count as intersecting""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 30] + }, + { + "description": "Email", + "page_number": 2, + "label_bounding_box": [10, 10, 50, 30], # Same coordinates but different page + "entry_bounding_box": [60, 10, 150, 30] + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("SUCCESS" in msg for msg in messages)) + self.assertFalse(any("FAILURE" in msg for msg in messages)) + + def test_entry_height_too_small(self): + """Test that entry box height is checked against font size""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 20], # Height is 10 + "entry_text": { + "font_size": 14 # Font size larger than height + } + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages)) + self.assertFalse(any("SUCCESS" in msg for msg in messages)) + + def test_entry_height_adequate(self): + """Test that adequate entry box height passes""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 30], # Height is 20 + "entry_text": { + "font_size": 14 # Font size smaller than height + } + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("SUCCESS" in msg for msg in messages)) + self.assertFalse(any("FAILURE" in msg for msg in messages)) + + def test_default_font_size(self): + """Test that default font size is used when not specified""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 20], # Height is 10 + "entry_text": {} # No font_size specified, should use default 14 + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages)) + self.assertFalse(any("SUCCESS" in msg for msg in messages)) + + def test_no_entry_text(self): + """Test that missing entry_text doesn't cause height check""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [60, 10, 150, 20] # Small height but no entry_text + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("SUCCESS" in msg for msg in messages)) + self.assertFalse(any("FAILURE" in msg for msg in messages)) + + def test_multiple_errors_limit(self): + """Test that error messages are limited to prevent excessive output""" + fields = [] + # Create many overlapping fields + for i in range(25): + fields.append({ + "description": f"Field{i}", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], # All overlap + "entry_bounding_box": [20, 15, 60, 35] # All overlap + }) + + data = {"form_fields": fields} + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + # Should abort after ~20 messages + self.assertTrue(any("Aborting" in msg for msg in messages)) + # Should have some FAILURE messages but not hundreds + failure_count = sum(1 for msg in messages if "FAILURE" in msg) + self.assertGreater(failure_count, 0) + self.assertLess(len(messages), 30) # Should be limited + + def test_edge_touching_boxes(self): + """Test that boxes touching at edges don't count as intersecting""" + data = { + "form_fields": [ + { + "description": "Name", + "page_number": 1, + "label_bounding_box": [10, 10, 50, 30], + "entry_bounding_box": [50, 10, 150, 30] # Touches at x=50 + } + ] + } + + stream = self.create_json_stream(data) + messages = get_bounding_box_messages(stream) + self.assertTrue(any("SUCCESS" in msg for msg in messages)) + self.assertFalse(any("FAILURE" in msg for msg in messages)) + + +if __name__ == '__main__': + unittest.main() diff --git a/account/admin/skills/pdf/scripts/check_fillable_fields.py b/account/admin/skills/pdf/scripts/check_fillable_fields.py new file mode 100644 index 0000000..36dfb95 --- /dev/null +++ b/account/admin/skills/pdf/scripts/check_fillable_fields.py @@ -0,0 +1,11 @@ +import sys +from pypdf import PdfReader + + + + +reader = PdfReader(sys.argv[1]) +if (reader.get_fields()): + print("This PDF has fillable form fields") +else: + print("This PDF does not have fillable form fields; you will need to visually determine where to enter data") diff --git a/account/admin/skills/pdf/scripts/convert_pdf_to_images.py b/account/admin/skills/pdf/scripts/convert_pdf_to_images.py new file mode 100644 index 0000000..7939cef --- /dev/null +++ b/account/admin/skills/pdf/scripts/convert_pdf_to_images.py @@ -0,0 +1,33 @@ +import os +import sys + +from pdf2image import convert_from_path + + + + +def convert(pdf_path, output_dir, max_dim=1000): + images = convert_from_path(pdf_path, dpi=200) + + for i, image in enumerate(images): + width, height = image.size + if width > max_dim or height > max_dim: + scale_factor = min(max_dim / width, max_dim / height) + new_width = int(width * scale_factor) + new_height = int(height * scale_factor) + image = image.resize((new_width, new_height)) + + image_path = os.path.join(output_dir, f"page_{i+1}.png") + image.save(image_path) + print(f"Saved page {i+1} as {image_path} (size: {image.size})") + + print(f"Converted {len(images)} pages to PNG images") + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: convert_pdf_to_images.py [input pdf] [output directory]") + sys.exit(1) + pdf_path = sys.argv[1] + output_directory = sys.argv[2] + convert(pdf_path, output_directory) diff --git a/account/admin/skills/pdf/scripts/create_validation_image.py b/account/admin/skills/pdf/scripts/create_validation_image.py new file mode 100644 index 0000000..10eadd8 --- /dev/null +++ b/account/admin/skills/pdf/scripts/create_validation_image.py @@ -0,0 +1,37 @@ +import json +import sys + +from PIL import Image, ImageDraw + + + + +def create_validation_image(page_number, fields_json_path, input_path, output_path): + with open(fields_json_path, 'r') as f: + data = json.load(f) + + img = Image.open(input_path) + draw = ImageDraw.Draw(img) + num_boxes = 0 + + for field in data["form_fields"]: + if field["page_number"] == page_number: + entry_box = field['entry_bounding_box'] + label_box = field['label_bounding_box'] + draw.rectangle(entry_box, outline='red', width=2) + draw.rectangle(label_box, outline='blue', width=2) + num_boxes += 2 + + img.save(output_path) + print(f"Created validation image at {output_path} with {num_boxes} bounding boxes") + + +if __name__ == "__main__": + if len(sys.argv) != 5: + print("Usage: create_validation_image.py [page number] [fields.json file] [input image path] [output image path]") + sys.exit(1) + page_number = int(sys.argv[1]) + fields_json_path = sys.argv[2] + input_image_path = sys.argv[3] + output_image_path = sys.argv[4] + create_validation_image(page_number, fields_json_path, input_image_path, output_image_path) diff --git a/account/admin/skills/pdf/scripts/extract_form_field_info.py b/account/admin/skills/pdf/scripts/extract_form_field_info.py new file mode 100644 index 0000000..64cd470 --- /dev/null +++ b/account/admin/skills/pdf/scripts/extract_form_field_info.py @@ -0,0 +1,122 @@ +import json +import sys + +from pypdf import PdfReader + + + + +def get_full_annotation_field_id(annotation): + components = [] + while annotation: + field_name = annotation.get('/T') + if field_name: + components.append(field_name) + annotation = annotation.get('/Parent') + return ".".join(reversed(components)) if components else None + + +def make_field_dict(field, field_id): + field_dict = {"field_id": field_id} + ft = field.get('/FT') + if ft == "/Tx": + field_dict["type"] = "text" + elif ft == "/Btn": + field_dict["type"] = "checkbox" + states = field.get("/_States_", []) + if len(states) == 2: + if "/Off" in states: + field_dict["checked_value"] = states[0] if states[0] != "/Off" else states[1] + field_dict["unchecked_value"] = "/Off" + else: + print(f"Unexpected state values for checkbox `${field_id}`. Its checked and unchecked values may not be correct; if you're trying to check it, visually verify the results.") + field_dict["checked_value"] = states[0] + field_dict["unchecked_value"] = states[1] + elif ft == "/Ch": + field_dict["type"] = "choice" + states = field.get("/_States_", []) + field_dict["choice_options"] = [{ + "value": state[0], + "text": state[1], + } for state in states] + else: + field_dict["type"] = f"unknown ({ft})" + return field_dict + + +def get_field_info(reader: PdfReader): + fields = reader.get_fields() + + field_info_by_id = {} + possible_radio_names = set() + + for field_id, field in fields.items(): + if field.get("/Kids"): + if field.get("/FT") == "/Btn": + possible_radio_names.add(field_id) + continue + field_info_by_id[field_id] = make_field_dict(field, field_id) + + + radio_fields_by_id = {} + + for page_index, page in enumerate(reader.pages): + annotations = page.get('/Annots', []) + for ann in annotations: + field_id = get_full_annotation_field_id(ann) + if field_id in field_info_by_id: + field_info_by_id[field_id]["page"] = page_index + 1 + field_info_by_id[field_id]["rect"] = ann.get('/Rect') + elif field_id in possible_radio_names: + try: + on_values = [v for v in ann["/AP"]["/N"] if v != "/Off"] + except KeyError: + continue + if len(on_values) == 1: + rect = ann.get("/Rect") + if field_id not in radio_fields_by_id: + radio_fields_by_id[field_id] = { + "field_id": field_id, + "type": "radio_group", + "page": page_index + 1, + "radio_options": [], + } + radio_fields_by_id[field_id]["radio_options"].append({ + "value": on_values[0], + "rect": rect, + }) + + fields_with_location = [] + for field_info in field_info_by_id.values(): + if "page" in field_info: + fields_with_location.append(field_info) + else: + print(f"Unable to determine location for field id: {field_info.get('field_id')}, ignoring") + + def sort_key(f): + if "radio_options" in f: + rect = f["radio_options"][0]["rect"] or [0, 0, 0, 0] + else: + rect = f.get("rect") or [0, 0, 0, 0] + adjusted_position = [-rect[1], rect[0]] + return [f.get("page"), adjusted_position] + + sorted_fields = fields_with_location + list(radio_fields_by_id.values()) + sorted_fields.sort(key=sort_key) + + return sorted_fields + + +def write_field_info(pdf_path: str, json_output_path: str): + reader = PdfReader(pdf_path) + field_info = get_field_info(reader) + with open(json_output_path, "w") as f: + json.dump(field_info, f, indent=2) + print(f"Wrote {len(field_info)} fields to {json_output_path}") + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: extract_form_field_info.py [input pdf] [output json]") + sys.exit(1) + write_field_info(sys.argv[1], sys.argv[2]) diff --git a/account/admin/skills/pdf/scripts/extract_form_structure.py b/account/admin/skills/pdf/scripts/extract_form_structure.py new file mode 100644 index 0000000..f219e7d --- /dev/null +++ b/account/admin/skills/pdf/scripts/extract_form_structure.py @@ -0,0 +1,115 @@ +""" +Extract form structure from a non-fillable PDF. + +This script analyzes the PDF to find: +- Text labels with their exact coordinates +- Horizontal lines (row boundaries) +- Checkboxes (small rectangles) + +Output: A JSON file with the form structure that can be used to generate +accurate field coordinates for filling. + +Usage: python extract_form_structure.py +""" + +import json +import sys +import pdfplumber + + +def extract_form_structure(pdf_path): + structure = { + "pages": [], + "labels": [], + "lines": [], + "checkboxes": [], + "row_boundaries": [] + } + + with pdfplumber.open(pdf_path) as pdf: + for page_num, page in enumerate(pdf.pages, 1): + structure["pages"].append({ + "page_number": page_num, + "width": float(page.width), + "height": float(page.height) + }) + + words = page.extract_words() + for word in words: + structure["labels"].append({ + "page": page_num, + "text": word["text"], + "x0": round(float(word["x0"]), 1), + "top": round(float(word["top"]), 1), + "x1": round(float(word["x1"]), 1), + "bottom": round(float(word["bottom"]), 1) + }) + + for line in page.lines: + if abs(float(line["x1"]) - float(line["x0"])) > page.width * 0.5: + structure["lines"].append({ + "page": page_num, + "y": round(float(line["top"]), 1), + "x0": round(float(line["x0"]), 1), + "x1": round(float(line["x1"]), 1) + }) + + for rect in page.rects: + width = float(rect["x1"]) - float(rect["x0"]) + height = float(rect["bottom"]) - float(rect["top"]) + if 5 <= width <= 15 and 5 <= height <= 15 and abs(width - height) < 2: + structure["checkboxes"].append({ + "page": page_num, + "x0": round(float(rect["x0"]), 1), + "top": round(float(rect["top"]), 1), + "x1": round(float(rect["x1"]), 1), + "bottom": round(float(rect["bottom"]), 1), + "center_x": round((float(rect["x0"]) + float(rect["x1"])) / 2, 1), + "center_y": round((float(rect["top"]) + float(rect["bottom"])) / 2, 1) + }) + + lines_by_page = {} + for line in structure["lines"]: + page = line["page"] + if page not in lines_by_page: + lines_by_page[page] = [] + lines_by_page[page].append(line["y"]) + + for page, y_coords in lines_by_page.items(): + y_coords = sorted(set(y_coords)) + for i in range(len(y_coords) - 1): + structure["row_boundaries"].append({ + "page": page, + "row_top": y_coords[i], + "row_bottom": y_coords[i + 1], + "row_height": round(y_coords[i + 1] - y_coords[i], 1) + }) + + return structure + + +def main(): + if len(sys.argv) != 3: + print("Usage: extract_form_structure.py ") + sys.exit(1) + + pdf_path = sys.argv[1] + output_path = sys.argv[2] + + print(f"Extracting structure from {pdf_path}...") + structure = extract_form_structure(pdf_path) + + with open(output_path, "w") as f: + json.dump(structure, f, indent=2) + + print(f"Found:") + print(f" - {len(structure['pages'])} pages") + print(f" - {len(structure['labels'])} text labels") + print(f" - {len(structure['lines'])} horizontal lines") + print(f" - {len(structure['checkboxes'])} checkboxes") + print(f" - {len(structure['row_boundaries'])} row boundaries") + print(f"Saved to {output_path}") + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/pdf/scripts/fill_fillable_fields.py b/account/admin/skills/pdf/scripts/fill_fillable_fields.py new file mode 100644 index 0000000..51c2600 --- /dev/null +++ b/account/admin/skills/pdf/scripts/fill_fillable_fields.py @@ -0,0 +1,98 @@ +import json +import sys + +from pypdf import PdfReader, PdfWriter + +from extract_form_field_info import get_field_info + + + + +def fill_pdf_fields(input_pdf_path: str, fields_json_path: str, output_pdf_path: str): + with open(fields_json_path) as f: + fields = json.load(f) + fields_by_page = {} + for field in fields: + if "value" in field: + field_id = field["field_id"] + page = field["page"] + if page not in fields_by_page: + fields_by_page[page] = {} + fields_by_page[page][field_id] = field["value"] + + reader = PdfReader(input_pdf_path) + + has_error = False + field_info = get_field_info(reader) + fields_by_ids = {f["field_id"]: f for f in field_info} + for field in fields: + existing_field = fields_by_ids.get(field["field_id"]) + if not existing_field: + has_error = True + print(f"ERROR: `{field['field_id']}` is not a valid field ID") + elif field["page"] != existing_field["page"]: + has_error = True + print(f"ERROR: Incorrect page number for `{field['field_id']}` (got {field['page']}, expected {existing_field['page']})") + else: + if "value" in field: + err = validation_error_for_field_value(existing_field, field["value"]) + if err: + print(err) + has_error = True + if has_error: + sys.exit(1) + + writer = PdfWriter(clone_from=reader) + for page, field_values in fields_by_page.items(): + writer.update_page_form_field_values(writer.pages[page - 1], field_values, auto_regenerate=False) + + writer.set_need_appearances_writer(True) + + with open(output_pdf_path, "wb") as f: + writer.write(f) + + +def validation_error_for_field_value(field_info, field_value): + field_type = field_info["type"] + field_id = field_info["field_id"] + if field_type == "checkbox": + checked_val = field_info["checked_value"] + unchecked_val = field_info["unchecked_value"] + if field_value != checked_val and field_value != unchecked_val: + return f'ERROR: Invalid value "{field_value}" for checkbox field "{field_id}". The checked value is "{checked_val}" and the unchecked value is "{unchecked_val}"' + elif field_type == "radio_group": + option_values = [opt["value"] for opt in field_info["radio_options"]] + if field_value not in option_values: + return f'ERROR: Invalid value "{field_value}" for radio group field "{field_id}". Valid values are: {option_values}' + elif field_type == "choice": + choice_values = [opt["value"] for opt in field_info["choice_options"]] + if field_value not in choice_values: + return f'ERROR: Invalid value "{field_value}" for choice field "{field_id}". Valid values are: {choice_values}' + return None + + +def monkeypatch_pydpf_method(): + from pypdf.generic import DictionaryObject + from pypdf.constants import FieldDictionaryAttributes + + original_get_inherited = DictionaryObject.get_inherited + + def patched_get_inherited(self, key: str, default = None): + result = original_get_inherited(self, key, default) + if key == FieldDictionaryAttributes.Opt: + if isinstance(result, list) and all(isinstance(v, list) and len(v) == 2 for v in result): + result = [r[0] for r in result] + return result + + DictionaryObject.get_inherited = patched_get_inherited + + +if __name__ == "__main__": + if len(sys.argv) != 4: + print("Usage: fill_fillable_fields.py [input pdf] [field_values.json] [output pdf]") + sys.exit(1) + monkeypatch_pydpf_method() + input_pdf = sys.argv[1] + fields_json = sys.argv[2] + output_pdf = sys.argv[3] + fill_pdf_fields(input_pdf, fields_json, output_pdf) diff --git a/account/admin/skills/pdf/scripts/fill_pdf_form_with_annotations.py b/account/admin/skills/pdf/scripts/fill_pdf_form_with_annotations.py new file mode 100644 index 0000000..b430069 --- /dev/null +++ b/account/admin/skills/pdf/scripts/fill_pdf_form_with_annotations.py @@ -0,0 +1,107 @@ +import json +import sys + +from pypdf import PdfReader, PdfWriter +from pypdf.annotations import FreeText + + + + +def transform_from_image_coords(bbox, image_width, image_height, pdf_width, pdf_height): + x_scale = pdf_width / image_width + y_scale = pdf_height / image_height + + left = bbox[0] * x_scale + right = bbox[2] * x_scale + + top = pdf_height - (bbox[1] * y_scale) + bottom = pdf_height - (bbox[3] * y_scale) + + return left, bottom, right, top + + +def transform_from_pdf_coords(bbox, pdf_height): + left = bbox[0] + right = bbox[2] + + pypdf_top = pdf_height - bbox[1] + pypdf_bottom = pdf_height - bbox[3] + + return left, pypdf_bottom, right, pypdf_top + + +def fill_pdf_form(input_pdf_path, fields_json_path, output_pdf_path): + + with open(fields_json_path, "r") as f: + fields_data = json.load(f) + + reader = PdfReader(input_pdf_path) + writer = PdfWriter() + + writer.append(reader) + + pdf_dimensions = {} + for i, page in enumerate(reader.pages): + mediabox = page.mediabox + pdf_dimensions[i + 1] = [mediabox.width, mediabox.height] + + annotations = [] + for field in fields_data["form_fields"]: + page_num = field["page_number"] + + page_info = next(p for p in fields_data["pages"] if p["page_number"] == page_num) + pdf_width, pdf_height = pdf_dimensions[page_num] + + if "pdf_width" in page_info: + transformed_entry_box = transform_from_pdf_coords( + field["entry_bounding_box"], + float(pdf_height) + ) + else: + image_width = page_info["image_width"] + image_height = page_info["image_height"] + transformed_entry_box = transform_from_image_coords( + field["entry_bounding_box"], + image_width, image_height, + float(pdf_width), float(pdf_height) + ) + + if "entry_text" not in field or "text" not in field["entry_text"]: + continue + entry_text = field["entry_text"] + text = entry_text["text"] + if not text: + continue + + font_name = entry_text.get("font", "Arial") + font_size = str(entry_text.get("font_size", 14)) + "pt" + font_color = entry_text.get("font_color", "000000") + + annotation = FreeText( + text=text, + rect=transformed_entry_box, + font=font_name, + font_size=font_size, + font_color=font_color, + border_color=None, + background_color=None, + ) + annotations.append(annotation) + writer.add_annotation(page_number=page_num - 1, annotation=annotation) + + with open(output_pdf_path, "wb") as output: + writer.write(output) + + print(f"Successfully filled PDF form and saved to {output_pdf_path}") + print(f"Added {len(annotations)} text annotations") + + +if __name__ == "__main__": + if len(sys.argv) != 4: + print("Usage: fill_pdf_form_with_annotations.py [input pdf] [fields.json] [output pdf]") + sys.exit(1) + input_pdf = sys.argv[1] + fields_json = sys.argv[2] + output_pdf = sys.argv[3] + + fill_pdf_form(input_pdf, fields_json, output_pdf) diff --git a/account/admin/skills/ppt-creator/.openakita-i18n.json b/account/admin/skills/ppt-creator/.openakita-i18n.json new file mode 100644 index 0000000..c9971b3 --- /dev/null +++ b/account/admin/skills/ppt-creator/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "PPT 演示文稿制作", + "description": "基于金字塔原理的专业演示文稿制作,支持 PPTX 生成、Marp/Reveal.js、数据图表、演讲备注和自评打分。" + } +} diff --git a/account/admin/skills/ppt-creator/SKILL.md b/account/admin/skills/ppt-creator/SKILL.md new file mode 100644 index 0000000..501bc00 --- /dev/null +++ b/account/admin/skills/ppt-creator/SKILL.md @@ -0,0 +1,394 @@ +--- +name: openakita/skills@ppt-creator +description: Create professional presentations using the Pyramid Principle methodology. Supports PPTX generation, Marp/Reveal.js Markdown slides, chart creation, speaker notes, and self-evaluation rubrics. Minimal intake form to rapid output workflow. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# PPT Creator — 专业演示文稿制作 + +## When to Use + +- 用户需要制作商业演示文稿(汇报、路演、培训、产品介绍) +- 需要将非结构化的想法整理为逻辑清晰的幻灯片 +- 需要生成包含数据图表的演示文稿 +- 需要自动生成演讲稿/备注 +- 需要将 Markdown 转换为演示文稿格式(Marp / Reveal.js) +- 需要评估已有 PPT 的质量 + +--- + +## Prerequisites + +### 必需工具 + +| 工具 | 用途 | 安装方式 | +|------|------|---------| +| Python ≥ 3.10 | 运行生成脚本 | 系统预装 | +| `python-pptx` | 生成 PPTX 文件 | `pip install python-pptx` | + +### 可选工具 + +| 工具 | 用途 | 安装方式 | +|------|------|---------| +| `marp-cli` | Markdown → PPT/PDF | `npm install -g @marp-team/marp-cli` | +| `matplotlib` | 数据图表生成 | `pip install matplotlib` | +| `Pillow` | 图片处理 | `pip install Pillow` | +| `plotly` | 交互式图表 | `pip install plotly kaleido` | + +### 验证安装 + +```bash +python -c "from pptx import Presentation; print('python-pptx OK')" +marp --version # 可选 +``` + +--- + +## Instructions + +### 核心方法论:金字塔原理(Pyramid Principle) + +本技能采用 Barbara Minto 的金字塔原理组织幻灯片结构: + +``` + ┌──────────────┐ + │ 核心结论 │ ← 1 句话概括 + └──────┬───────┘ + ┌─────────┼─────────┐ + ┌────┴────┐ ┌──┴───┐ ┌──┴────┐ + │ 论点 A │ │论点 B│ │论点 C │ ← 3 个支撑论点 + └────┬────┘ └──┬───┘ └──┬────┘ + 证据1-3 证据1-3 证据1-3 ← 每个论点 2-3 条证据 +``` + +**原则:** +1. **结论先行** — 每页幻灯片的标题就是该页的结论 +2. **以上统下** — 上层观点是下层内容的概括 +3. **归类分组** — 同层内容属于同一逻辑范畴 +4. **逻辑递进** — 同层内容有明确的排列顺序(时间、结构、重要性) + +### 演示文稿结构模板 + +| 幻灯片 | 内容 | 时间 | +|--------|------|------| +| 封面 | 标题、副标题、演讲者、日期 | — | +| 目录/议程 | 演讲结构概览 | 30s | +| 背景/问题 | 现状描述、痛点阐述 | 45-60s | +| 核心论点 1 | 第一个支撑论点 + 数据/案例 | 45-60s | +| 核心论点 2 | 第二个支撑论点 + 数据/案例 | 45-60s | +| 核心论点 3 | 第三个支撑论点 + 数据/案例 | 45-60s | +| 方案/建议 | 具体行动方案 | 45-60s | +| 时间线/路线图 | 实施计划 | 45-60s | +| 总结 | 回扣核心结论、关键要点 | 30s | +| Q&A / 致谢 | 联系方式、讨论时间 | — | + +--- + +## Workflows + +### Workflow 1: 快速创建(Minimal Intake Form) + +**步骤 1 — 收集关键信息** + +向用户询问以下 5 个要素(尽量精简): + +| # | 问题 | 示例回答 | +|---|------|---------| +| 1 | 演讲主题是什么? | "Q4 产品路线图汇报" | +| 2 | 目标受众是谁? | "公司管理层" | +| 3 | 核心结论/诉求? | "需要追加 30% 研发预算" | +| 4 | 有哪些关键数据或论据? | "用户增长 200%、竞品分析、技术债" | +| 5 | 幻灯片数量偏好? | "10-15 页" | + +如果用户只给了主题,根据常识和金字塔原理自行推导其余要素,并在生成前确认。 + +**步骤 2 — 构建金字塔结构** + +基于收集的信息,输出结构大纲: + +``` +核心结论:追加 30% 研发预算以支撑用户增长 +├── 论点A:用户量爆发增长(200%)带来系统压力 +│ ├── 证据:月活跃用户趋势图 +│ ├── 证据:服务器负载数据 +│ └── 证据:用户投诉工单增长 +├── 论点B:竞品正在加速投入 +│ ├── 证据:竞品融资/招聘动态 +│ ├── 证据:功能对比矩阵 +│ └── 证据:市场份额变化 +└── 论点C:技术债已影响迭代速度 + ├── 证据:发布周期对比 + ├── 证据:Bug 趋势 + └── 证据:开发者满意度调查 +``` + +**步骤 3 — 生成幻灯片内容** + +逐页编写: +- **标题**:一句完整的结论性陈述(非主题词) +- **正文**:3-5 个要点,每点 ≤ 15 字 +- **图表/数据**:识别需要数据可视化的页面 +- **备注**:45-60 秒的演讲脚本 + +**步骤 4 — 输出文件** + +根据用户需要选择输出格式(见 Output Format 部分)。 + +--- + +### Workflow 2: 数据图表生成 + +**支持的图表类型** + +| 图表 | 适用场景 | 库 | +|------|---------|-----| +| 柱状图 | 对比数据 | matplotlib / plotly | +| 折线图 | 趋势变化 | matplotlib / plotly | +| 饼图 | 占比分布 | matplotlib / plotly | +| 散点图 | 相关性分析 | matplotlib / plotly | +| 瀑布图 | 增减分解 | plotly | +| 热力图 | 矩阵数据 | matplotlib / seaborn | +| 雷达图 | 多维对比 | matplotlib | + +**图表设计原则** + +1. **标题即结论** — 图表标题描述洞察而非数据("销售额同比增长 40%" vs "Q4 销售数据") +2. **极简配色** — 使用 2-3 种颜色,重点数据用强调色 +3. **去除噪音** — 删除网格线、多余边框、3D 效果 +4. **标注关键值** — 在图表上直接标注最重要的数据点 +5. **适当留白** — 图表不超过幻灯片面积的 60% + +**生成图表的 Python 示例** + +```python +import matplotlib.pyplot as plt +import matplotlib + +matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei'] +matplotlib.rcParams['axes.unicode_minus'] = False + +fig, ax = plt.subplots(figsize=(10, 6)) +categories = ['Q1', 'Q2', 'Q3', 'Q4'] +values = [120, 180, 240, 350] +colors = ['#e0e0e0', '#e0e0e0', '#e0e0e0', '#4A90D9'] + +ax.bar(categories, values, color=colors, width=0.6) +ax.set_title('Q4 营收突破 350 万,环比增长 46%', fontsize=16, fontweight='bold', pad=20) +ax.spines['top'].set_visible(False) +ax.spines['right'].set_visible(False) + +for i, v in enumerate(values): + ax.text(i, v + 5, f'{v}万', ha='center', fontsize=12) + +plt.tight_layout() +plt.savefig('chart_revenue.png', dpi=200, bbox_inches='tight') +``` + +--- + +### Workflow 3: 演讲备注生成 + +为每张幻灯片生成 45-60 秒的演讲稿: + +**规则:** +1. 开头:过渡语连接上一页("接下来看...""那么...") +2. 中间:用口语化表达阐述幻灯片要点 +3. 结尾:用一句话总结本页核心信息 +4. 字数:中文约 150-200 字 ≈ 45-60 秒 +5. 标注停顿点:`[停顿]`、`[看向观众]` +6. 标注交互点:`[提问]`、`[举手调查]` + +**示例:** + +``` +那么我们来看第一个关键发现。[停顿] + +过去一个季度,我们的月活跃用户从 50 万增长到了 150 万, +同比增长了 200%。[看向观众] 这是一个非常可喜的数字, +但同时也带来了挑战。 + +大家可以看到右边的图表,随着用户量的激增, +我们的服务器平均响应时间从 200 毫秒上升到了 800 毫秒, +高峰期甚至出现过 5 秒的延迟。[停顿] + +这意味着什么?如果我们不尽快扩容, +用户体验将会显著下降,这直接影响留存率。 +``` + +--- + +### Workflow 4: 自评打分 + +生成完成后,用以下 rubric 评估质量: + +| 维度 | 满分 | 评分标准 | +|------|------|---------| +| 结构逻辑 | 25 | 金字塔结构完整、论点 MECE | +| 视觉设计 | 20 | 一致的配色、排版、留白 | +| 数据可视化 | 20 | 图表清晰、标题即结论 | +| 演讲备注 | 15 | 流畅、口语化、时间合适 | +| 受众适配 | 10 | 语言风格匹配目标受众 | +| 行动导向 | 10 | 明确的 CTA 和下一步 | + +目标分数:≥ 80/100。低于 80 分时自动修订弱项。 + +--- + +## Output Format + +### 格式 1: PPTX 文件(python-pptx) + +使用 `python-pptx` 生成标准 PowerPoint 文件: + +```python +from pptx import Presentation +from pptx.util import Inches, Pt +from pptx.enum.text import PP_ALIGN + +prs = Presentation() +prs.slide_width = Inches(13.333) +prs.slide_height = Inches(7.5) + +slide_layout = prs.slide_layouts[6] # blank layout +slide = prs.slides.add_slide(slide_layout) + +title_shape = slide.shapes.add_textbox(Inches(0.8), Inches(0.5), Inches(11.7), Inches(1.2)) +tf = title_shape.text_frame +tf.text = "Q4 营收同比增长 46%,超额完成目标" +tf.paragraphs[0].font.size = Pt(28) +tf.paragraphs[0].font.bold = True + +notes_slide = slide.notes_slide +notes_slide.notes_text_frame.text = "演讲备注内容..." + +prs.save('presentation.pptx') +``` + +### 格式 2: Marp Markdown + +```markdown +--- +marp: true +theme: default +paginate: true +header: "公司名 | Q4 汇报" +footer: "机密" +--- + +# Q4 产品路线图汇报 +### 需要追加 30% 研发预算以支撑用户增长 + +**演讲者** | 日期 + +--- + +## 用户量爆发增长带来系统压力 + +- 月活从 50 万 → 150 万(+200%) +- 服务器响应时间 200ms → 800ms +- 用户投诉工单增长 3 倍 + +![bg right:40%](chart_growth.png) + +--- +``` + +转换命令: + +```bash +marp slides.md --pptx -o presentation.pptx +marp slides.md --pdf -o presentation.pdf +marp slides.md --html -o presentation.html +``` + +### 格式 3: Reveal.js HTML + +```html + + + + + + + +
+
+
+

Q4 产品路线图汇报

+

需要追加 30% 研发预算以支撑用户增长

+ +
+
+

用户量爆发增长带来系统压力

+
    +
  • 月活从 50 万 → 150 万(+200%)
  • +
  • 服务器响应时间 200ms → 800ms
  • +
+ +
+
+
+ + + + +``` + +### 格式 4: PNG 图表 + +每张数据图表单独输出为 PNG,分辨率 ≥ 200 DPI。 + +--- + +## Common Pitfalls + +### 1. 标题写成了"主题词"而非"结论" + +**错误**:幻灯片标题 "Q4 销售数据" +**正确**:幻灯片标题 "Q4 销售额同比增长 40%,超额完成年度目标" + +### 2. 每页内容过多 + +每张幻灯片不超过 5 个要点,每个要点不超过 15 个汉字。当内容过多时拆分为多页。 + +### 3. 配色不一致 + +整套 PPT 使用同一配色方案。推荐的安全配色: +- 主色 1 种 + 强调色 1 种 + 灰色系 +- 避免使用超过 4 种颜色 + +### 4. 图表与结论脱节 + +每张图表必须支撑其所在页的标题结论。如果图表无法直接证明标题,要么修改图表要么修改标题。 + +### 5. 忽略受众水平 + +- 给管理层:聚焦商业影响、省略技术细节 +- 给技术团队:可以深入架构、代码层面 +- 给客户:突出价值和收益 + +### 6. 中文字体兼容 + +使用 python-pptx 时确保指定中文字体: + +```python +from pptx.util import Pt +paragraph.font.name = 'Microsoft YaHei' +``` + +### 7. 演讲时间估算不准 + +中文演讲速度约 200-250 字/分钟。10 页幻灯片 × 1 分钟/页 = 10 分钟演讲。如果用户要求 30 分钟演讲,需要约 25-30 页内容。 + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 公司 PPT 模板路径 +- 品牌配色和字体 +- 常用 PPT 结构模板 +- 特定行业/场景的幻灯片范例 diff --git a/account/admin/skills/pptx/LICENSE.txt b/account/admin/skills/pptx/LICENSE.txt new file mode 100644 index 0000000..c55ab42 --- /dev/null +++ b/account/admin/skills/pptx/LICENSE.txt @@ -0,0 +1,30 @@ +© 2025 Anthropic, PBC. All rights reserved. + +LICENSE: Use of these materials (including all code, prompts, assets, files, +and other components of this Skill) is governed by your agreement with +Anthropic regarding use of Anthropic's services. If no separate agreement +exists, use is governed by Anthropic's Consumer Terms of Service or +Commercial Terms of Service, as applicable: +https://www.anthropic.com/legal/consumer-terms +https://www.anthropic.com/legal/commercial-terms +Your applicable agreement is referred to as the "Agreement." "Services" are +as defined in the Agreement. + +ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the +contrary, users may not: + +- Extract these materials from the Services or retain copies of these + materials outside the Services +- Reproduce or copy these materials, except for temporary copies created + automatically during authorized use of the Services +- Create derivative works based on these materials +- Distribute, sublicense, or transfer these materials to any third party +- Make, offer to sell, sell, or import any inventions embodied in these + materials +- Reverse engineer, decompile, or disassemble these materials + +The receipt, viewing, or possession of these materials does not convey or +imply any license or right beyond those expressly granted above. + +Anthropic retains all right, title, and interest in these materials, +including all copyrights, patents, and other intellectual property rights. diff --git a/account/admin/skills/pptx/SKILL.md b/account/admin/skills/pptx/SKILL.md new file mode 100644 index 0000000..762794b --- /dev/null +++ b/account/admin/skills/pptx/SKILL.md @@ -0,0 +1,232 @@ +--- +name: openakita/skills@pptx +description: "Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions \"deck,\" \"slides,\" \"presentation,\" or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill." +license: Proprietary. LICENSE.txt has complete terms +--- + +# PPTX Skill + +## Quick Reference + +| Task | Guide | +|------|-------| +| Read/analyze content | `python -m markitdown presentation.pptx` | +| Edit or create from template | Read [editing.md](editing.md) | +| Create from scratch | Read [pptxgenjs.md](pptxgenjs.md) | + +--- + +## Reading Content + +```bash +# Text extraction +python -m markitdown presentation.pptx + +# Visual overview +python scripts/thumbnail.py presentation.pptx + +# Raw XML +python scripts/office/unpack.py presentation.pptx unpacked/ +``` + +--- + +## Editing Workflow + +**Read [editing.md](editing.md) for full details.** + +1. Analyze template with `thumbnail.py` +2. Unpack → manipulate slides → edit content → clean → pack + +--- + +## Creating from Scratch + +**Read [pptxgenjs.md](pptxgenjs.md) for full details.** + +Use when no template or reference presentation is available. + +--- + +## Design Ideas + +**Don't create boring slides.** Plain bullets on a white background won't impress anyone. Consider ideas from this list for each slide. + +### Before Starting + +- **Pick a bold, content-informed color palette**: The palette should feel designed for THIS topic. If swapping your colors into a completely different presentation would still "work," you haven't made specific enough choices. +- **Dominance over equality**: One color should dominate (60-70% visual weight), with 1-2 supporting tones and one sharp accent. Never give all colors equal weight. +- **Dark/light contrast**: Dark backgrounds for title + conclusion slides, light for content ("sandwich" structure). Or commit to dark throughout for a premium feel. +- **Commit to a visual motif**: Pick ONE distinctive element and repeat it — rounded image frames, icons in colored circles, thick single-side borders. Carry it across every slide. + +### Color Palettes + +Choose colors that match your topic — don't default to generic blue. Use these palettes as inspiration: + +| Theme | Primary | Secondary | Accent | +|-------|---------|-----------|--------| +| **Midnight Executive** | `1E2761` (navy) | `CADCFC` (ice blue) | `FFFFFF` (white) | +| **Forest & Moss** | `2C5F2D` (forest) | `97BC62` (moss) | `F5F5F5` (cream) | +| **Coral Energy** | `F96167` (coral) | `F9E795` (gold) | `2F3C7E` (navy) | +| **Warm Terracotta** | `B85042` (terracotta) | `E7E8D1` (sand) | `A7BEAE` (sage) | +| **Ocean Gradient** | `065A82` (deep blue) | `1C7293` (teal) | `21295C` (midnight) | +| **Charcoal Minimal** | `36454F` (charcoal) | `F2F2F2` (off-white) | `212121` (black) | +| **Teal Trust** | `028090` (teal) | `00A896` (seafoam) | `02C39A` (mint) | +| **Berry & Cream** | `6D2E46` (berry) | `A26769` (dusty rose) | `ECE2D0` (cream) | +| **Sage Calm** | `84B59F` (sage) | `69A297` (eucalyptus) | `50808E` (slate) | +| **Cherry Bold** | `990011` (cherry) | `FCF6F5` (off-white) | `2F3C7E` (navy) | + +### For Each Slide + +**Every slide needs a visual element** — image, chart, icon, or shape. Text-only slides are forgettable. + +**Layout options:** +- Two-column (text left, illustration on right) +- Icon + text rows (icon in colored circle, bold header, description below) +- 2x2 or 2x3 grid (image on one side, grid of content blocks on other) +- Half-bleed image (full left or right side) with content overlay + +**Data display:** +- Large stat callouts (big numbers 60-72pt with small labels below) +- Comparison columns (before/after, pros/cons, side-by-side options) +- Timeline or process flow (numbered steps, arrows) + +**Visual polish:** +- Icons in small colored circles next to section headers +- Italic accent text for key stats or taglines + +### Typography + +**Choose an interesting font pairing** — don't default to Arial. Pick a header font with personality and pair it with a clean body font. + +| Header Font | Body Font | +|-------------|-----------| +| Georgia | Calibri | +| Arial Black | Arial | +| Calibri | Calibri Light | +| Cambria | Calibri | +| Trebuchet MS | Calibri | +| Impact | Arial | +| Palatino | Garamond | +| Consolas | Calibri | + +| Element | Size | +|---------|------| +| Slide title | 36-44pt bold | +| Section header | 20-24pt bold | +| Body text | 14-16pt | +| Captions | 10-12pt muted | + +### Spacing + +- 0.5" minimum margins +- 0.3-0.5" between content blocks +- Leave breathing room—don't fill every inch + +### Avoid (Common Mistakes) + +- **Don't repeat the same layout** — vary columns, cards, and callouts across slides +- **Don't center body text** — left-align paragraphs and lists; center only titles +- **Don't skimp on size contrast** — titles need 36pt+ to stand out from 14-16pt body +- **Don't default to blue** — pick colors that reflect the specific topic +- **Don't mix spacing randomly** — choose 0.3" or 0.5" gaps and use consistently +- **Don't style one slide and leave the rest plain** — commit fully or keep it simple throughout +- **Don't create text-only slides** — add images, icons, charts, or visual elements; avoid plain title + bullets +- **Don't forget text box padding** — when aligning lines or shapes with text edges, set `margin: 0` on the text box or offset the shape to account for padding +- **Don't use low-contrast elements** — icons AND text need strong contrast against the background; avoid light text on light backgrounds or dark text on dark backgrounds +- **NEVER use accent lines under titles** — these are a hallmark of AI-generated slides; use whitespace or background color instead + +--- + +## QA (Required) + +**Assume there are problems. Your job is to find them.** + +Your first render is almost never correct. Approach QA as a bug hunt, not a confirmation step. If you found zero issues on first inspection, you weren't looking hard enough. + +### Content QA + +```bash +python -m markitdown output.pptx +``` + +Check for missing content, typos, wrong order. + +**When using templates, check for leftover placeholder text:** + +```bash +python -m markitdown output.pptx | grep -iE "xxxx|lorem|ipsum|this.*(page|slide).*layout" +``` + +If grep returns results, fix them before declaring success. + +### Visual QA + +**⚠️ USE SUBAGENTS** — even for 2-3 slides. You've been staring at the code and will see what you expect, not what's there. Subagents have fresh eyes. + +Convert slides to images (see [Converting to Images](#converting-to-images)), then use this prompt: + +``` +Visually inspect these slides. Assume there are issues — find them. + +Look for: +- Overlapping elements (text through shapes, lines through words, stacked elements) +- Text overflow or cut off at edges/box boundaries +- Decorative lines positioned for single-line text but title wrapped to two lines +- Source citations or footers colliding with content above +- Elements too close (< 0.3" gaps) or cards/sections nearly touching +- Uneven gaps (large empty area in one place, cramped in another) +- Insufficient margin from slide edges (< 0.5") +- Columns or similar elements not aligned consistently +- Low-contrast text (e.g., light gray text on cream-colored background) +- Low-contrast icons (e.g., dark icons on dark backgrounds without a contrasting circle) +- Text boxes too narrow causing excessive wrapping +- Leftover placeholder content + +For each slide, list issues or areas of concern, even if minor. + +Read and analyze these images: +1. /path/to/slide-01.jpg (Expected: [brief description]) +2. /path/to/slide-02.jpg (Expected: [brief description]) + +Report ALL issues found, including minor ones. +``` + +### Verification Loop + +1. Generate slides → Convert to images → Inspect +2. **List issues found** (if none found, look again more critically) +3. Fix issues +4. **Re-verify affected slides** — one fix often creates another problem +5. Repeat until a full pass reveals no new issues + +**Do not declare success until you've completed at least one fix-and-verify cycle.** + +--- + +## Converting to Images + +Convert presentations to individual slide images for visual inspection: + +```bash +python scripts/office/soffice.py --headless --convert-to pdf output.pptx +pdftoppm -jpeg -r 150 output.pdf slide +``` + +This creates `slide-01.jpg`, `slide-02.jpg`, etc. + +To re-render specific slides after fixes: + +```bash +pdftoppm -jpeg -r 150 -f N -l N output.pdf slide-fixed +``` + +--- + +## Dependencies + +- `pip install "markitdown[pptx]"` - text extraction +- `pip install Pillow` - thumbnail grids +- `npm install -g pptxgenjs` - creating from scratch +- LibreOffice (`soffice`) - PDF conversion (auto-configured for sandboxed environments via `scripts/office/soffice.py`) +- Poppler (`pdftoppm`) - PDF to images diff --git a/account/admin/skills/pptx/editing.md b/account/admin/skills/pptx/editing.md new file mode 100644 index 0000000..f873e8a --- /dev/null +++ b/account/admin/skills/pptx/editing.md @@ -0,0 +1,205 @@ +# Editing Presentations + +## Template-Based Workflow + +When using an existing presentation as a template: + +1. **Analyze existing slides**: + ```bash + python scripts/thumbnail.py template.pptx + python -m markitdown template.pptx + ``` + Review `thumbnails.jpg` to see layouts, and markitdown output to see placeholder text. + +2. **Plan slide mapping**: For each content section, choose a template slide. + + ⚠️ **USE VARIED LAYOUTS** — monotonous presentations are a common failure mode. Don't default to basic title + bullet slides. Actively seek out: + - Multi-column layouts (2-column, 3-column) + - Image + text combinations + - Full-bleed images with text overlay + - Quote or callout slides + - Section dividers + - Stat/number callouts + - Icon grids or icon + text rows + + **Avoid:** Repeating the same text-heavy layout for every slide. + + Match content type to layout style (e.g., key points → bullet slide, team info → multi-column, testimonials → quote slide). + +3. **Unpack**: `python scripts/office/unpack.py template.pptx unpacked/` + +4. **Build presentation** (do this yourself, not with subagents): + - Delete unwanted slides (remove from ``) + - Duplicate slides you want to reuse (`add_slide.py`) + - Reorder slides in `` + - **Complete all structural changes before step 5** + +5. **Edit content**: Update text in each `slide{N}.xml`. + **Use subagents here if available** — slides are separate XML files, so subagents can edit in parallel. + +6. **Clean**: `python scripts/clean.py unpacked/` + +7. **Pack**: `python scripts/office/pack.py unpacked/ output.pptx --original template.pptx` + +--- + +## Scripts + +| Script | Purpose | +|--------|---------| +| `unpack.py` | Extract and pretty-print PPTX | +| `add_slide.py` | Duplicate slide or create from layout | +| `clean.py` | Remove orphaned files | +| `pack.py` | Repack with validation | +| `thumbnail.py` | Create visual grid of slides | + +### unpack.py + +```bash +python scripts/office/unpack.py input.pptx unpacked/ +``` + +Extracts PPTX, pretty-prints XML, escapes smart quotes. + +### add_slide.py + +```bash +python scripts/add_slide.py unpacked/ slide2.xml # Duplicate slide +python scripts/add_slide.py unpacked/ slideLayout2.xml # From layout +``` + +Prints `` to add to `` at desired position. + +### clean.py + +```bash +python scripts/clean.py unpacked/ +``` + +Removes slides not in ``, unreferenced media, orphaned rels. + +### pack.py + +```bash +python scripts/office/pack.py unpacked/ output.pptx --original input.pptx +``` + +Validates, repairs, condenses XML, re-encodes smart quotes. + +### thumbnail.py + +```bash +python scripts/thumbnail.py input.pptx [output_prefix] [--cols N] +``` + +Creates `thumbnails.jpg` with slide filenames as labels. Default 3 columns, max 12 per grid. + +**Use for template analysis only** (choosing layouts). For visual QA, use `soffice` + `pdftoppm` to create full-resolution individual slide images—see SKILL.md. + +--- + +## Slide Operations + +Slide order is in `ppt/presentation.xml` → ``. + +**Reorder**: Rearrange `` elements. + +**Delete**: Remove ``, then run `clean.py`. + +**Add**: Use `add_slide.py`. Never manually copy slide files—the script handles notes references, Content_Types.xml, and relationship IDs that manual copying misses. + +--- + +## Editing Content + +**Subagents:** If available, use them here (after completing step 4). Each slide is a separate XML file, so subagents can edit in parallel. In your prompt to subagents, include: +- The slide file path(s) to edit +- **"Use the Edit tool for all changes"** +- The formatting rules and common pitfalls below + +For each slide: +1. Read the slide's XML +2. Identify ALL placeholder content—text, images, charts, icons, captions +3. Replace each placeholder with final content + +**Use the Edit tool, not sed or Python scripts.** The Edit tool forces specificity about what to replace and where, yielding better reliability. + +### Formatting Rules + +- **Bold all headers, subheadings, and inline labels**: Use `b="1"` on ``. This includes: + - Slide titles + - Section headers within a slide + - Inline labels like (e.g.: "Status:", "Description:") at the start of a line +- **Never use unicode bullets (•)**: Use proper list formatting with `` or `` +- **Bullet consistency**: Let bullets inherit from the layout. Only specify `` or ``. + +--- + +## Common Pitfalls + +### Template Adaptation + +When source content has fewer items than the template: +- **Remove excess elements entirely** (images, shapes, text boxes), don't just clear text +- Check for orphaned visuals after clearing text content +- Run visual QA to catch mismatched counts + +When replacing text with different length content: +- **Shorter replacements**: Usually safe +- **Longer replacements**: May overflow or wrap unexpectedly +- Test with visual QA after text changes +- Consider truncating or splitting content to fit the template's design constraints + +**Template slots ≠ Source items**: If template has 4 team members but source has 3 users, delete the 4th member's entire group (image + text boxes), not just the text. + +### Multi-Item Content + +If source has multiple items (numbered lists, multiple sections), create separate `` elements for each — **never concatenate into one string**. + +**❌ WRONG** — all items in one paragraph: +```xml + + Step 1: Do the first thing. Step 2: Do the second thing. + +``` + +**✅ CORRECT** — separate paragraphs with bold headers: +```xml + + + Step 1 + + + + Do the first thing. + + + + Step 2 + + +``` + +Copy `` from the original paragraph to preserve line spacing. Use `b="1"` on headers. + +### Smart Quotes + +Handled automatically by unpack/pack. But the Edit tool converts smart quotes to ASCII. + +**When adding new text with quotes, use XML entities:** + +```xml +the “Agreement” +``` + +| Character | Name | Unicode | XML Entity | +|-----------|------|---------|------------| +| `“` | Left double quote | U+201C | `“` | +| `”` | Right double quote | U+201D | `”` | +| `‘` | Left single quote | U+2018 | `‘` | +| `’` | Right single quote | U+2019 | `’` | + +### Other + +- **Whitespace**: Use `xml:space="preserve"` on `` with leading/trailing spaces +- **XML parsing**: Use `defusedxml.minidom`, not `xml.etree.ElementTree` (corrupts namespaces) diff --git a/account/admin/skills/pptx/html2pptx.md b/account/admin/skills/pptx/html2pptx.md new file mode 100644 index 0000000..106adf7 --- /dev/null +++ b/account/admin/skills/pptx/html2pptx.md @@ -0,0 +1,625 @@ +# HTML to PowerPoint Guide + +Convert HTML slides to PowerPoint presentations with accurate positioning using the `html2pptx.js` library. + +## Table of Contents + +1. [Creating HTML Slides](#creating-html-slides) +2. [Using the html2pptx Library](#using-the-html2pptx-library) +3. [Using PptxGenJS](#using-pptxgenjs) + +--- + +## Creating HTML Slides + +Every HTML slide must include proper body dimensions: + +### Layout Dimensions + +- **16:9** (default): `width: 720pt; height: 405pt` +- **4:3**: `width: 720pt; height: 540pt` +- **16:10**: `width: 720pt; height: 450pt` + +### Supported Elements + +- `

`, `

`-`

` - Text with styling +- `
    `, `
      ` - Lists (never use manual bullets •, -, *) +- ``, `` - Bold text (inline formatting) +- ``, `` - Italic text (inline formatting) +- `` - Underlined text (inline formatting) +- `` - Inline formatting with CSS styles (bold, italic, underline, color) +- `
      ` - Line breaks +- `
      ` with bg/border - Becomes shape +- `` - Images +- `class="placeholder"` - Reserved space for charts (returns `{ id, x, y, w, h }`) + +### Critical Text Rules + +**ALL text MUST be inside `

      `, `

      `-`

      `, `
        `, or `
          ` tags:** +- ✅ Correct: `

          Text here

          ` +- ❌ Wrong: `
          Text here
          ` - **Text will NOT appear in PowerPoint** +- ❌ Wrong: `Text` - **Text will NOT appear in PowerPoint** +- Text in `
          ` or `` without a text tag will be silently ignored + +**NEVER use manual bullet symbols (•, -, *, etc.)** - Use `
            ` or `
              ` lists instead + +**ONLY use web-safe fonts that are universally available:** +- ✅ Web-safe fonts: `Arial`, `Helvetica`, `Times New Roman`, `Georgia`, `Courier New`, `Verdana`, `Tahoma`, `Trebuchet MS`, `Impact`, `Comic Sans MS` +- ❌ Wrong: `'Segoe UI'`, `'SF Pro'`, `'Roboto'`, custom fonts - **Might cause rendering issues** + +### Styling + +- Use `display: flex` on body to prevent margin collapse from breaking overflow validation +- Use `margin` for spacing (padding included in size) +- Inline formatting: Use ``, ``, `` tags OR `` with CSS styles + - `` supports: `font-weight: bold`, `font-style: italic`, `text-decoration: underline`, `color: #rrggbb` + - `` does NOT support: `margin`, `padding` (not supported in PowerPoint text runs) + - Example: `Bold blue text` +- Flexbox works - positions calculated from rendered layout +- Use hex colors with `#` prefix in CSS +- **Text alignment**: Use CSS `text-align` (`center`, `right`, etc.) when needed as a hint to PptxGenJS for text formatting if text lengths are slightly off + +### Shape Styling (DIV elements only) + +**IMPORTANT: Backgrounds, borders, and shadows only work on `
              ` elements, NOT on text elements (`

              `, `

              `-`

              `, `
                `, `
                  `)** + +- **Backgrounds**: CSS `background` or `background-color` on `
                  ` elements only + - Example: `
                  ` - Creates a shape with background +- **Borders**: CSS `border` on `
                  ` elements converts to PowerPoint shape borders + - Supports uniform borders: `border: 2px solid #333333` + - Supports partial borders: `border-left`, `border-right`, `border-top`, `border-bottom` (rendered as line shapes) + - Example: `
                  ` +- **Border radius**: CSS `border-radius` on `
                  ` elements for rounded corners + - `border-radius: 50%` or higher creates circular shape + - Percentages <50% calculated relative to shape's smaller dimension + - Supports px and pt units (e.g., `border-radius: 8pt;`, `border-radius: 12px;`) + - Example: `
                  ` on 100x200px box = 25% of 100px = 25px radius +- **Box shadows**: CSS `box-shadow` on `
                  ` elements converts to PowerPoint shadows + - Supports outer shadows only (inset shadows are ignored to prevent corruption) + - Example: `
                  ` + - Note: Inset/inner shadows are not supported by PowerPoint and will be skipped + +### Icons & Gradients + +- **CRITICAL: Never use CSS gradients (`linear-gradient`, `radial-gradient`)** - They don't convert to PowerPoint +- **ALWAYS create gradient/icon PNGs FIRST using Sharp, then reference in HTML** +- For gradients: Rasterize SVG to PNG background images +- For icons: Rasterize react-icons SVG to PNG images +- All visual effects must be pre-rendered as raster images before HTML rendering + +**Rasterizing Icons with Sharp:** + +```javascript +const React = require('react'); +const ReactDOMServer = require('react-dom/server'); +const sharp = require('sharp'); +const { FaHome } = require('react-icons/fa'); + +async function rasterizeIconPng(IconComponent, color, size = "256", filename) { + const svgString = ReactDOMServer.renderToStaticMarkup( + React.createElement(IconComponent, { color: `#${color}`, size: size }) + ); + + // Convert SVG to PNG using Sharp + await sharp(Buffer.from(svgString)) + .png() + .toFile(filename); + + return filename; +} + +// Usage: Rasterize icon before using in HTML +const iconPath = await rasterizeIconPng(FaHome, "4472c4", "256", "home-icon.png"); +// Then reference in HTML: +``` + +**Rasterizing Gradients with Sharp:** + +```javascript +const sharp = require('sharp'); + +async function createGradientBackground(filename) { + const svg = ` + + + + + + + + `; + + await sharp(Buffer.from(svg)) + .png() + .toFile(filename); + + return filename; +} + +// Usage: Create gradient background before HTML +const bgPath = await createGradientBackground("gradient-bg.png"); +// Then in HTML: +``` + +### Example + +```html + + + + + + +
                  +

                  Recipe Title

                  +
                    +
                  • Item: Description
                  • +
                  +

                  Text with bold, italic, underline.

                  +
                  + + +
                  +

                  5

                  +
                  +
                  + + +``` + +## Using the html2pptx Library + +### Dependencies + +These libraries have been globally installed and are available to use: +- `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 + +const { slide, placeholders } = await html2pptx('slide1.html', pptx); + +// Add chart to placeholder area +if (placeholders.length > 0) { + slide.addChart(pptx.charts.LINE, chartData, placeholders[0]); +} + +await pptx.writeFile('output.pptx'); +``` + +### API Reference + +#### Function Signature +```javascript +await html2pptx(htmlFile, pres, options) +``` + +#### Parameters +- `htmlFile` (string): Path to HTML file (absolute or relative) +- `pres` (pptxgen): PptxGenJS presentation instance with layout already set +- `options` (object, optional): + - `tmpDir` (string): Temporary directory for generated files (default: `process.env.TMPDIR || '/tmp'`) + - `slide` (object): Existing slide to reuse (default: creates new slide) + +#### Returns +```javascript +{ + slide: pptxgenSlide, // The created/updated slide + placeholders: [ // Array of placeholder positions + { id: string, x: number, y: number, w: number, h: number }, + ... + ] +} +``` + +### Validation + +The library automatically validates and collects all errors before throwing: + +1. **HTML dimensions must match presentation layout** - Reports dimension mismatches +2. **Content must not overflow body** - Reports overflow with exact measurements +3. **CSS gradients** - Reports unsupported gradient usage +4. **Text element styling** - Reports backgrounds/borders/shadows on text elements (only allowed on divs) + +**All validation errors are collected and reported together** in a single error message, allowing you to fix all issues at once instead of one at a time. + +### Working with Placeholders + +```javascript +const { slide, placeholders } = await html2pptx('slide.html', pptx); + +// Use first placeholder +slide.addChart(pptx.charts.BAR, data, placeholders[0]); + +// Find by ID +const chartArea = placeholders.find(p => p.id === 'chart-area'); +slide.addChart(pptx.charts.LINE, data, chartArea); +``` + +### Complete Example + +```javascript +const pptxgen = require('pptxgenjs'); +const html2pptx = require('./html2pptx'); + +async function createPresentation() { + const pptx = new pptxgen(); + pptx.layout = 'LAYOUT_16x9'; + pptx.author = 'Your Name'; + pptx.title = 'My Presentation'; + + // Slide 1: Title + const { slide: slide1 } = await html2pptx('slides/title.html', pptx); + + // Slide 2: Content with chart + const { slide: slide2, placeholders } = await html2pptx('slides/data.html', pptx); + + const chartData = [{ + name: 'Sales', + labels: ['Q1', 'Q2', 'Q3', 'Q4'], + values: [4500, 5500, 6200, 7100] + }]; + + slide2.addChart(pptx.charts.BAR, chartData, { + ...placeholders[0], + showTitle: true, + title: 'Quarterly Sales', + showCatAxisTitle: true, + catAxisTitle: 'Quarter', + showValAxisTitle: true, + valAxisTitle: 'Sales ($000s)' + }); + + // Save + await pptx.writeFile({ fileName: 'presentation.pptx' }); + console.log('Presentation created successfully!'); +} + +createPresentation().catch(console.error); +``` + +## Using PptxGenJS + +After converting HTML to slides with `html2pptx`, you'll use PptxGenJS to add dynamic content like charts, images, and additional elements. + +### ⚠️ Critical Rules + +#### Colors +- **NEVER use `#` prefix** with hex colors in PptxGenJS - causes file corruption +- ✅ Correct: `color: "FF0000"`, `fill: { color: "0066CC" }` +- ❌ Wrong: `color: "#FF0000"` (breaks document) + +### Adding Images + +Always calculate aspect ratios from actual image dimensions: + +```javascript +// Get image dimensions: identify image.png | grep -o '[0-9]* x [0-9]*' +const imgWidth = 1860, imgHeight = 1519; // From actual file +const aspectRatio = imgWidth / imgHeight; + +const h = 3; // Max height +const w = h * aspectRatio; +const x = (10 - w) / 2; // Center on 16:9 slide + +slide.addImage({ path: "chart.png", x, y: 1.5, w, h }); +``` + +### Adding Text + +```javascript +// Rich text with formatting +slide.addText([ + { text: "Bold ", options: { bold: true } }, + { text: "Italic ", options: { italic: true } }, + { text: "Normal" } +], { + x: 1, y: 2, w: 8, h: 1 +}); +``` + +### Adding Shapes + +```javascript +// Rectangle +slide.addShape(pptx.shapes.RECTANGLE, { + x: 1, y: 1, w: 3, h: 2, + fill: { color: "4472C4" }, + line: { color: "000000", width: 2 } +}); + +// Circle +slide.addShape(pptx.shapes.OVAL, { + x: 5, y: 1, w: 2, h: 2, + fill: { color: "ED7D31" } +}); + +// Rounded rectangle +slide.addShape(pptx.shapes.ROUNDED_RECTANGLE, { + x: 1, y: 4, w: 3, h: 1.5, + fill: { color: "70AD47" }, + rectRadius: 0.2 +}); +``` + +### Adding Charts + +**Required for most charts:** Axis labels using `catAxisTitle` (category) and `valAxisTitle` (value). + +**Chart Data Format:** +- Use **single series with all labels** for simple bar/line charts +- Each series creates a separate legend entry +- Labels array defines X-axis values + +**Time Series Data - Choose Correct Granularity:** +- **< 30 days**: Use daily grouping (e.g., "10-01", "10-02") - avoid monthly aggregation that creates single-point charts +- **30-365 days**: Use monthly grouping (e.g., "2024-01", "2024-02") +- **> 365 days**: Use yearly grouping (e.g., "2023", "2024") +- **Validate**: Charts with only 1 data point likely indicate incorrect aggregation for the time period + +```javascript +const { slide, placeholders } = await html2pptx('slide.html', pptx); + +// CORRECT: Single series with all labels +slide.addChart(pptx.charts.BAR, [{ + name: "Sales 2024", + labels: ["Q1", "Q2", "Q3", "Q4"], + values: [4500, 5500, 6200, 7100] +}], { + ...placeholders[0], // Use placeholder position + barDir: 'col', // 'col' = vertical bars, 'bar' = horizontal + showTitle: true, + title: 'Quarterly Sales', + showLegend: false, // No legend needed for single series + // Required axis labels + showCatAxisTitle: true, + catAxisTitle: 'Quarter', + showValAxisTitle: true, + valAxisTitle: 'Sales ($000s)', + // Optional: Control scaling (adjust min based on data range for better visualization) + valAxisMaxVal: 8000, + valAxisMinVal: 0, // Use 0 for counts/amounts; for clustered data (e.g., 4500-7100), consider starting closer to min value + valAxisMajorUnit: 2000, // Control y-axis label spacing to prevent crowding + catAxisLabelRotate: 45, // Rotate labels if crowded + dataLabelPosition: 'outEnd', + dataLabelColor: '000000', + // Use single color for single-series charts + chartColors: ["4472C4"] // All bars same color +}); +``` + +#### Scatter Chart + +**IMPORTANT**: Scatter chart data format is unusual - first series contains X-axis values, subsequent series contain Y-values: + +```javascript +// Prepare data +const data1 = [{ x: 10, y: 20 }, { x: 15, y: 25 }, { x: 20, y: 30 }]; +const data2 = [{ x: 12, y: 18 }, { x: 18, y: 22 }]; + +const allXValues = [...data1.map(d => d.x), ...data2.map(d => d.x)]; + +slide.addChart(pptx.charts.SCATTER, [ + { name: 'X-Axis', values: allXValues }, // First series = X values + { name: 'Series 1', values: data1.map(d => d.y) }, // Y values only + { name: 'Series 2', values: data2.map(d => d.y) } // Y values only +], { + x: 1, y: 1, w: 8, h: 4, + lineSize: 0, // 0 = no connecting lines + lineDataSymbol: 'circle', + lineDataSymbolSize: 6, + showCatAxisTitle: true, + catAxisTitle: 'X Axis', + showValAxisTitle: true, + valAxisTitle: 'Y Axis', + chartColors: ["4472C4", "ED7D31"] +}); +``` + +#### 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, + // Required axis labels + showCatAxisTitle: true, + catAxisTitle: 'Month', + showValAxisTitle: true, + valAxisTitle: 'Temperature (°F)', + // Optional: Y-axis range (set min based on data range for better visualization) + valAxisMinVal: 0, // For ranges starting at 0 (counts, percentages, etc.) + valAxisMaxVal: 60, + valAxisMajorUnit: 20, // Control y-axis label spacing to prevent crowding (e.g., 10, 20, 25) + // valAxisMinVal: 30, // PREFERRED: For data clustered in a range (e.g., 32-55 or ratings 3-5), start axis closer to min value to show variation + // Optional: Chart colors + chartColors: ["4472C4", "ED7D31", "A5A5A5"] +}); +``` + +#### Pie Chart (No Axis Labels Required) + +**CRITICAL**: Pie charts require a **single data series** with all categories in the `labels` array and corresponding values in the `values` array. + +```javascript +slide.addChart(pptx.charts.PIE, [{ + name: "Market Share", + labels: ["Product A", "Product B", "Other"], // All categories in one array + values: [35, 45, 20] // All values in one array +}], { + x: 2, y: 1, w: 6, h: 4, + showPercent: true, + showLegend: true, + legendPos: 'r', // right + chartColors: ["4472C4", "ED7D31", "A5A5A5"] +}); +``` + +#### Multiple Data 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 + +**CRITICAL**: Use hex colors **without** the `#` prefix - including `#` causes file corruption. + +**Align chart colors with your chosen design palette**, ensuring sufficient contrast and distinctiveness for data visualization. Adjust colors for: +- Strong contrast between adjacent series +- Readability against slide backgrounds +- Accessibility (avoid red-green only combinations) + +```javascript +// Example: Ocean palette-inspired chart colors (adjusted for contrast) +const chartColors = ["16A085", "FF6B9D", "2C3E50", "F39C12", "9B59B6"]; + +// Single-series chart: Use one color for all bars/points +slide.addChart(pptx.charts.BAR, [{ + name: "Sales", + labels: ["Q1", "Q2", "Q3", "Q4"], + values: [4500, 5500, 6200, 7100] +}], { + ...placeholders[0], + chartColors: ["16A085"], // All bars same color + showLegend: false +}); + +// Multi-series chart: Each series gets a different color +slide.addChart(pptx.charts.LINE, [ + { name: "Product A", labels: ["Q1", "Q2", "Q3"], values: [10, 20, 30] }, + { name: "Product B", labels: ["Q1", "Q2", "Q3"], values: [15, 25, 20] } +], { + ...placeholders[0], + chartColors: ["16A085", "FF6B9D"] // One color per series +}); +``` + +### Adding Tables + +Tables can be added with basic or advanced formatting: + +#### Basic Table + +```javascript +slide.addTable([ + ["Header 1", "Header 2", "Header 3"], + ["Row 1, Col 1", "Row 1, Col 2", "Row 1, Col 3"], + ["Row 2, Col 1", "Row 2, Col 2", "Row 2, Col 3"] +], { + x: 0.5, + y: 1, + w: 9, + h: 3, + border: { pt: 1, color: "999999" }, + fill: { color: "F1F1F1" } +}); +``` + +#### Table with Custom Formatting + +```javascript +const tableData = [ + // Header row with custom styling + [ + { 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 } } + ], + // Data rows + ["Product A", "$50M", "+15%"], + ["Product B", "$35M", "+22%"], + ["Product C", "$28M", "+8%"] +]; + +slide.addTable(tableData, { + x: 1, + y: 1.5, + w: 8, + h: 3, + colW: [3, 2.5, 2.5], // Column widths + rowH: [0.5, 0.6, 0.6, 0.6], // Row heights + border: { pt: 1, color: "CCCCCC" }, + align: "center", + valign: "middle", + fontSize: 14 +}); +``` + +#### Table with Merged Cells + +```javascript +const mergedTableData = [ + [ + { text: "Q1 Results", options: { colspan: 3, fill: { color: "4472C4" }, color: "FFFFFF", bold: true } } + ], + ["Product", "Sales", "Market Share"], + ["Product A", "$25M", "35%"], + ["Product B", "$18M", "25%"] +]; + +slide.addTable(mergedTableData, { + x: 1, + y: 1, + w: 8, + h: 2.5, + colW: [3, 2.5, 2.5], + border: { pt: 1, color: "DDDDDD" } +}); +``` + +### Table Options + +Common table options: +- `x, y, w, h` - Position and size +- `colW` - Array of column widths (in inches) +- `rowH` - Array of row heights (in inches) +- `border` - Border style: `{ pt: 1, color: "999999" }` +- `fill` - Background color (no # prefix) +- `align` - Text alignment: "left", "center", "right" +- `valign` - Vertical alignment: "top", "middle", "bottom" +- `fontSize` - Text size +- `autoPage` - Auto-create new slides if content overflows \ No newline at end of file diff --git a/account/admin/skills/pptx/ooxml.md b/account/admin/skills/pptx/ooxml.md new file mode 100644 index 0000000..951b3cf --- /dev/null +++ b/account/admin/skills/pptx/ooxml.md @@ -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 ``**: ``, ``, `` +- **Whitespace**: Add `xml:space='preserve'` to `` elements with leading/trailing spaces +- **Unicode**: Escape characters in ASCII content: `"` becomes `“` +- **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 `` and `` elements to indicate clean state + +## Presentation Structure + +### Basic Slide Structure +```xml + + + + + ... + ... + + + + +``` + +### Text Box / Shape with Text +```xml + + + + + + + + + + + + + + + + + + + + + + Slide Title + + + + +``` + +### Text Formatting +```xml + + + + Bold Text + + + + + + Italic Text + + + + + + Underlined + + + + + + + + + + Highlighted Text + + + + + + + + + + Colored Arial 24pt + + + + + + + + + + Formatted text + +``` + +### Lists +```xml + + + + + + + First bullet point + + + + + + + + + + First numbered item + + + + + + + + + + Indented bullet + + +``` + +### Shapes +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### Images +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### Tables +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + Cell 1 + + + + + + + + + + + Cell 2 + + + + + + + + + +``` + +### Slide Layouts + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## File Updates + +When adding content, update these files: + +**`ppt/_rels/presentation.xml.rels`:** +```xml + + +``` + +**`ppt/slides/_rels/slide1.xml.rels`:** +```xml + + +``` + +**`[Content_Types].xml`:** +```xml + + + +``` + +**`ppt/presentation.xml`:** +```xml + + + + +``` + +**`docProps/app.xml`:** Update slide count and statistics +```xml +2 +10 +50 +``` + +## 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 `` +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 `` elements in `` +2. The order of `` elements determines slide order +3. Keep slide IDs and relationship IDs unchanged + +Example: +```xml + + + + + + + + + + + + + +``` + +### Deleting a Slide +1. **Remove from `ppt/presentation.xml`**: Delete the `` 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 `“` +- **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 \ No newline at end of file diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd new file mode 100644 index 0000000..6454ef9 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd @@ -0,0 +1,1499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd new file mode 100644 index 0000000..afa4f46 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd new file mode 100644 index 0000000..64e66b8 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd @@ -0,0 +1,1085 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd new file mode 100644 index 0000000..687eea8 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd @@ -0,0 +1,11 @@ + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd new file mode 100644 index 0000000..6ac81b0 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd @@ -0,0 +1,3081 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd new file mode 100644 index 0000000..1dbf051 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..f1af17d --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..0a185ab --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd new file mode 100644 index 0000000..14ef488 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd @@ -0,0 +1,1676 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd new file mode 100644 index 0000000..c20f3bf --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd new file mode 100644 index 0000000..ac60252 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd new file mode 100644 index 0000000..424b8ba --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd new file mode 100644 index 0000000..2bddce2 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd new file mode 100644 index 0000000..8a8c18b --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd new file mode 100644 index 0000000..5c42706 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd new file mode 100644 index 0000000..853c341 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd new file mode 100644 index 0000000..da835ee --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd new file mode 100644 index 0000000..87ad265 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd new file mode 100644 index 0000000..9e86f1b --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd new file mode 100644 index 0000000..d0be42e --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd @@ -0,0 +1,4439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd new file mode 100644 index 0000000..8821dd1 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd @@ -0,0 +1,570 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd new file mode 100644 index 0000000..ca2575c --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd new file mode 100644 index 0000000..dd079e6 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..3dd6cf6 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..f1041e3 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd new file mode 100644 index 0000000..9c5b7a6 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd @@ -0,0 +1,3646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd new file mode 100644 index 0000000..0f13678 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd @@ -0,0 +1,116 @@ + + + + + + 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 + + + + + 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: + <schema . . .> + . . . + <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. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + 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. + + + + + + In due course, we should install the relevant ISO 2- and 3-letter + codes as the enumerated possible values . . . + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd new file mode 100644 index 0000000..a6de9d2 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd new file mode 100644 index 0000000..10e978b --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd new file mode 100644 index 0000000..4248bf7 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd new file mode 100644 index 0000000..5649746 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/mce/mc.xsd b/account/admin/skills/pptx/ooxml/schemas/mce/mc.xsd new file mode 100644 index 0000000..ef72545 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/mce/mc.xsd @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd new file mode 100644 index 0000000..f65f777 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd @@ -0,0 +1,560 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd new file mode 100644 index 0000000..6b00755 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd new file mode 100644 index 0000000..f321d33 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd new file mode 100644 index 0000000..364c6a9 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd new file mode 100644 index 0000000..fed9d15 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd new file mode 100644 index 0000000..680cf15 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd @@ -0,0 +1,4 @@ + + + + diff --git a/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd new file mode 100644 index 0000000..89ada90 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/account/admin/skills/pptx/ooxml/scripts/pack.py b/account/admin/skills/pptx/ooxml/scripts/pack.py new file mode 100644 index 0000000..68bc088 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/pack.py @@ -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 [--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() diff --git a/account/admin/skills/pptx/ooxml/scripts/unpack.py b/account/admin/skills/pptx/ooxml/scripts/unpack.py new file mode 100644 index 0000000..4938798 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/unpack.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +"""Unpack and format XML contents of Office files (.docx, .pptx, .xlsx)""" + +import random +import sys +import defusedxml.minidom +import zipfile +from pathlib import Path + +# Get command line arguments +assert len(sys.argv) == 3, "Usage: python unpack.py " +input_file, output_dir = sys.argv[1], sys.argv[2] + +# Extract and format +output_path = Path(output_dir) +output_path.mkdir(parents=True, exist_ok=True) +zipfile.ZipFile(input_file).extractall(output_path) + +# Pretty print all XML files +xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) +for xml_file in xml_files: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="ascii")) + +# For .docx files, suggest an RSID for tracked changes +if input_file.endswith(".docx"): + suggested_rsid = "".join(random.choices("0123456789ABCDEF", k=8)) + print(f"Suggested RSID for edit session: {suggested_rsid}") diff --git a/account/admin/skills/pptx/ooxml/scripts/validate.py b/account/admin/skills/pptx/ooxml/scripts/validate.py new file mode 100644 index 0000000..508c589 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validate.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +""" +Command line tool to validate Office document XML files against XSD schemas and tracked changes. + +Usage: + python validate.py --original +""" + +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() + assert unpacked_dir.is_dir(), f"Error: {unpacked_dir} is not a directory" + assert original_file.is_file(), f"Error: {original_file} is not a file" + assert file_extension in [".docx", ".pptx", ".xlsx"], ( + 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() diff --git a/account/admin/skills/pptx/ooxml/scripts/validation/__init__.py b/account/admin/skills/pptx/ooxml/scripts/validation/__init__.py new file mode 100644 index 0000000..db092ec --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validation/__init__.py @@ -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", +] diff --git a/account/admin/skills/pptx/ooxml/scripts/validation/base.py b/account/admin/skills/pptx/ooxml/scripts/validation/base.py new file mode 100644 index 0000000..0681b19 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validation/base.py @@ -0,0 +1,951 @@ +""" +Base validator with common validation logic for document files. +""" + +import re +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. + """ + import lxml.etree + + 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: ' + ) + + 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 + """ + import tempfile + import zipfile + + # 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.") diff --git a/account/admin/skills/pptx/ooxml/scripts/validation/docx.py b/account/admin/skills/pptx/ooxml/scripts/validation/docx.py new file mode 100644 index 0000000..602c470 --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validation/docx.py @@ -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}: found within : {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}: within : {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.") diff --git a/account/admin/skills/pptx/ooxml/scripts/validation/pptx.py b/account/admin/skills/pptx/ooxml/scripts/validation/pptx.py new file mode 100644 index 0000000..66d5b1e --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validation/pptx.py @@ -0,0 +1,315 @@ +""" +Validator for PowerPoint presentation XML files against XSD schemas. +""" + +import re + +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.""" + import lxml.etree + + 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.""" + import lxml.etree + + 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.""" + import lxml.etree + + 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.""" + import lxml.etree + + 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.") diff --git a/account/admin/skills/pptx/ooxml/scripts/validation/redlining.py b/account/admin/skills/pptx/ooxml/scripts/validation/redlining.py new file mode 100644 index 0000000..7ed425e --- /dev/null +++ b/account/admin/skills/pptx/ooxml/scripts/validation/redlining.py @@ -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 Claude 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 Claude + del_elements = root.findall(".//w:del", self.namespaces) + ins_elements = root.findall(".//w:ins", self.namespaces) + + # Filter to only include changes by Claude + claude_del_elements = [ + elem + for elem in del_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == "Claude" + ] + claude_ins_elements = [ + elem + for elem in ins_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == "Claude" + ] + + # Redlining validation is only needed if tracked changes by Claude have been used. + if not claude_del_elements and not claude_ins_elements: + if self.verbose: + print("PASSED - No tracked changes by Claude 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 Claude's tracked changes from both documents + self._remove_claude_tracked_changes(original_root) + self._remove_claude_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 Claude 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 Claude's tracked changes", + "", + "Likely causes:", + " 1. Modified text inside another author's or tags", + " 2. Made edits without proper tracked changes", + " 3. Didn't nest inside when deleting another's insertion", + "", + "For pre-redlined documents, use correct patterns:", + " - To reject another's INSERTION: Nest inside their ", + " - To restore another's DELETION: Add new AFTER their ", + "", + ] + + # 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_claude_tracked_changes(self, root): + """Remove tracked changes authored by Claude 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) == "Claude": + to_remove.append(child) + for elem in to_remove: + parent.remove(elem) + + # Unwrap content in w:del elements where author is "Claude" + 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) == "Claude": + 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.") diff --git a/account/admin/skills/pptx/pptxgenjs.md b/account/admin/skills/pptx/pptxgenjs.md new file mode 100644 index 0000000..6bfed90 --- /dev/null +++ b/account/admin/skills/pptx/pptxgenjs.md @@ -0,0 +1,420 @@ +# PptxGenJS Tutorial + +## Setup & Basic Structure + +```javascript +const pptxgen = require("pptxgenjs"); + +let pres = new pptxgen(); +pres.layout = 'LAYOUT_16x9'; // or 'LAYOUT_16x10', 'LAYOUT_4x3', 'LAYOUT_WIDE' +pres.author = 'Your Name'; +pres.title = 'Presentation Title'; + +let slide = pres.addSlide(); +slide.addText("Hello World!", { x: 0.5, y: 0.5, fontSize: 36, color: "363636" }); + +pres.writeFile({ fileName: "Presentation.pptx" }); +``` + +## Layout Dimensions + +Slide dimensions (coordinates in inches): +- `LAYOUT_16x9`: 10" × 5.625" (default) +- `LAYOUT_16x10`: 10" × 6.25" +- `LAYOUT_4x3`: 10" × 7.5" +- `LAYOUT_WIDE`: 13.3" × 7.5" + +--- + +## Text & Formatting + +```javascript +// Basic text +slide.addText("Simple Text", { + x: 1, y: 1, w: 8, h: 2, fontSize: 24, fontFace: "Arial", + color: "363636", bold: true, align: "center", valign: "middle" +}); + +// Character spacing (use charSpacing, not letterSpacing which is silently ignored) +slide.addText("SPACED TEXT", { x: 1, y: 1, w: 8, h: 1, charSpacing: 6 }); + +// Rich text arrays +slide.addText([ + { text: "Bold ", options: { bold: true } }, + { text: "Italic ", options: { italic: true } } +], { x: 1, y: 3, w: 8, h: 1 }); + +// Multi-line text (requires breakLine: true) +slide.addText([ + { text: "Line 1", options: { breakLine: true } }, + { text: "Line 2", options: { breakLine: true } }, + { text: "Line 3" } // Last item doesn't need breakLine +], { x: 0.5, y: 0.5, w: 8, h: 2 }); + +// Text box margin (internal padding) +slide.addText("Title", { + x: 0.5, y: 0.3, w: 9, h: 0.6, + margin: 0 // Use 0 when aligning text with other elements like shapes or icons +}); +``` + +**Tip:** Text boxes have internal margin by default. Set `margin: 0` when you need text to align precisely with shapes, lines, or icons at the same x-position. + +--- + +## Lists & Bullets + +```javascript +// ✅ CORRECT: Multiple bullets +slide.addText([ + { text: "First item", options: { bullet: true, breakLine: true } }, + { text: "Second item", options: { bullet: true, breakLine: true } }, + { text: "Third item", options: { bullet: true } } +], { x: 0.5, y: 0.5, w: 8, h: 3 }); + +// ❌ WRONG: Never use unicode bullets +slide.addText("• First item", { ... }); // Creates double bullets + +// Sub-items and numbered lists +{ text: "Sub-item", options: { bullet: true, indentLevel: 1 } } +{ text: "First", options: { bullet: { type: "number" }, breakLine: true } } +``` + +--- + +## Shapes + +```javascript +slide.addShape(pres.shapes.RECTANGLE, { + x: 0.5, y: 0.8, w: 1.5, h: 3.0, + fill: { color: "FF0000" }, line: { color: "000000", width: 2 } +}); + +slide.addShape(pres.shapes.OVAL, { x: 4, y: 1, w: 2, h: 2, fill: { color: "0000FF" } }); + +slide.addShape(pres.shapes.LINE, { + x: 1, y: 3, w: 5, h: 0, line: { color: "FF0000", width: 3, dashType: "dash" } +}); + +// With transparency +slide.addShape(pres.shapes.RECTANGLE, { + x: 1, y: 1, w: 3, h: 2, + fill: { color: "0088CC", transparency: 50 } +}); + +// Rounded rectangle (rectRadius only works with ROUNDED_RECTANGLE, not RECTANGLE) +// ⚠️ Don't pair with rectangular accent overlays — they won't cover rounded corners. Use RECTANGLE instead. +slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { + x: 1, y: 1, w: 3, h: 2, + fill: { color: "FFFFFF" }, rectRadius: 0.1 +}); + +// With shadow +slide.addShape(pres.shapes.RECTANGLE, { + x: 1, y: 1, w: 3, h: 2, + fill: { color: "FFFFFF" }, + shadow: { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.15 } +}); +``` + +Shadow options: + +| Property | Type | Range | Notes | +|----------|------|-------|-------| +| `type` | string | `"outer"`, `"inner"` | | +| `color` | string | 6-char hex (e.g. `"000000"`) | No `#` prefix, no 8-char hex — see Common Pitfalls | +| `blur` | number | 0-100 pt | | +| `offset` | number | 0-200 pt | **Must be non-negative** — negative values corrupt the file | +| `angle` | number | 0-359 degrees | Direction the shadow falls (135 = bottom-right, 270 = upward) | +| `opacity` | number | 0.0-1.0 | Use this for transparency, never encode in color string | + +To cast a shadow upward (e.g. on a footer bar), use `angle: 270` with a positive offset — do **not** use a negative offset. + +**Note**: Gradient fills are not natively supported. Use a gradient image as a background instead. + +--- + +## Images + +### Image Sources + +```javascript +// From file path +slide.addImage({ path: "images/chart.png", x: 1, y: 1, w: 5, h: 3 }); + +// From URL +slide.addImage({ path: "https://example.com/image.jpg", x: 1, y: 1, w: 5, h: 3 }); + +// From base64 (faster, no file I/O) +slide.addImage({ data: "image/png;base64,iVBORw0KGgo...", x: 1, y: 1, w: 5, h: 3 }); +``` + +### Image Options + +```javascript +slide.addImage({ + path: "image.png", + x: 1, y: 1, w: 5, h: 3, + rotate: 45, // 0-359 degrees + rounding: true, // Circular crop + transparency: 50, // 0-100 + flipH: true, // Horizontal flip + flipV: false, // Vertical flip + altText: "Description", // Accessibility + hyperlink: { url: "https://example.com" } +}); +``` + +### Image Sizing Modes + +```javascript +// Contain - fit inside, preserve ratio +{ sizing: { type: 'contain', w: 4, h: 3 } } + +// Cover - fill area, preserve ratio (may crop) +{ sizing: { type: 'cover', w: 4, h: 3 } } + +// Crop - cut specific portion +{ sizing: { type: 'crop', x: 0.5, y: 0.5, w: 2, h: 2 } } +``` + +### Calculate Dimensions (preserve aspect ratio) + +```javascript +const origWidth = 1978, origHeight = 923, maxHeight = 3.0; +const calcWidth = maxHeight * (origWidth / origHeight); +const centerX = (10 - calcWidth) / 2; + +slide.addImage({ path: "image.png", x: centerX, y: 1.2, w: calcWidth, h: maxHeight }); +``` + +### Supported Formats + +- **Standard**: PNG, JPG, GIF (animated GIFs work in Microsoft 365) +- **SVG**: Works in modern PowerPoint/Microsoft 365 + +--- + +## Icons + +Use react-icons to generate SVG icons, then rasterize to PNG for universal compatibility. + +### Setup + +```javascript +const React = require("react"); +const ReactDOMServer = require("react-dom/server"); +const sharp = require("sharp"); +const { FaCheckCircle, FaChartLine } = require("react-icons/fa"); + +function renderIconSvg(IconComponent, color = "#000000", size = 256) { + return ReactDOMServer.renderToStaticMarkup( + React.createElement(IconComponent, { color, size: String(size) }) + ); +} + +async function iconToBase64Png(IconComponent, color, size = 256) { + const svg = renderIconSvg(IconComponent, color, size); + const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer(); + return "image/png;base64," + pngBuffer.toString("base64"); +} +``` + +### Add Icon to Slide + +```javascript +const iconData = await iconToBase64Png(FaCheckCircle, "#4472C4", 256); + +slide.addImage({ + data: iconData, + x: 1, y: 1, w: 0.5, h: 0.5 // Size in inches +}); +``` + +**Note**: Use size 256 or higher for crisp icons. The size parameter controls the rasterization resolution, not the display size on the slide (which is set by `w` and `h` in inches). + +### Icon Libraries + +Install: `npm install -g react-icons react react-dom sharp` + +Popular icon sets in react-icons: +- `react-icons/fa` - Font Awesome +- `react-icons/md` - Material Design +- `react-icons/hi` - Heroicons +- `react-icons/bi` - Bootstrap Icons + +--- + +## Slide Backgrounds + +```javascript +// Solid color +slide.background = { color: "F1F1F1" }; + +// Color with transparency +slide.background = { color: "FF3399", transparency: 50 }; + +// Image from URL +slide.background = { path: "https://example.com/bg.jpg" }; + +// Image from base64 +slide.background = { data: "image/png;base64,iVBORw0KGgo..." }; +``` + +--- + +## Tables + +```javascript +slide.addTable([ + ["Header 1", "Header 2"], + ["Cell 1", "Cell 2"] +], { + x: 1, y: 1, w: 8, h: 2, + border: { pt: 1, color: "999999" }, fill: { color: "F1F1F1" } +}); + +// Advanced with merged cells +let tableData = [ + [{ text: "Header", options: { fill: { color: "6699CC" }, color: "FFFFFF", bold: true } }, "Cell"], + [{ text: "Merged", options: { colspan: 2 } }] +]; +slide.addTable(tableData, { x: 1, y: 3.5, w: 8, colW: [4, 4] }); +``` + +--- + +## Charts + +```javascript +// Bar chart +slide.addChart(pres.charts.BAR, [{ + name: "Sales", labels: ["Q1", "Q2", "Q3", "Q4"], values: [4500, 5500, 6200, 7100] +}], { + x: 0.5, y: 0.6, w: 6, h: 3, barDir: 'col', + showTitle: true, title: 'Quarterly Sales' +}); + +// Line chart +slide.addChart(pres.charts.LINE, [{ + name: "Temp", labels: ["Jan", "Feb", "Mar"], values: [32, 35, 42] +}], { x: 0.5, y: 4, w: 6, h: 3, lineSize: 3, lineSmooth: true }); + +// Pie chart +slide.addChart(pres.charts.PIE, [{ + name: "Share", labels: ["A", "B", "Other"], values: [35, 45, 20] +}], { x: 7, y: 1, w: 5, h: 4, showPercent: true }); +``` + +### Better-Looking Charts + +Default charts look dated. Apply these options for a modern, clean appearance: + +```javascript +slide.addChart(pres.charts.BAR, chartData, { + x: 0.5, y: 1, w: 9, h: 4, barDir: "col", + + // Custom colors (match your presentation palette) + chartColors: ["0D9488", "14B8A6", "5EEAD4"], + + // Clean background + chartArea: { fill: { color: "FFFFFF" }, roundedCorners: true }, + + // Muted axis labels + catAxisLabelColor: "64748B", + valAxisLabelColor: "64748B", + + // Subtle grid (value axis only) + valGridLine: { color: "E2E8F0", size: 0.5 }, + catGridLine: { style: "none" }, + + // Data labels on bars + showValue: true, + dataLabelPosition: "outEnd", + dataLabelColor: "1E293B", + + // Hide legend for single series + showLegend: false, +}); +``` + +**Key styling options:** +- `chartColors: [...]` - hex colors for series/segments +- `chartArea: { fill, border, roundedCorners }` - chart background +- `catGridLine/valGridLine: { color, style, size }` - grid lines (`style: "none"` to hide) +- `lineSmooth: true` - curved lines (line charts) +- `legendPos: "r"` - legend position: "b", "t", "l", "r", "tr" + +--- + +## Slide Masters + +```javascript +pres.defineSlideMaster({ + title: 'TITLE_SLIDE', background: { color: '283A5E' }, + objects: [{ + placeholder: { options: { name: 'title', type: 'title', x: 1, y: 2, w: 8, h: 2 } } + }] +}); + +let titleSlide = pres.addSlide({ masterName: "TITLE_SLIDE" }); +titleSlide.addText("My Title", { placeholder: "title" }); +``` + +--- + +## Common Pitfalls + +⚠️ These issues cause file corruption, visual bugs, or broken output. Avoid them. + +1. **NEVER use "#" with hex colors** - causes file corruption + ```javascript + color: "FF0000" // ✅ CORRECT + color: "#FF0000" // ❌ WRONG + ``` + +2. **NEVER encode opacity in hex color strings** - 8-char colors (e.g., `"00000020"`) corrupt the file. Use the `opacity` property instead. + ```javascript + shadow: { type: "outer", blur: 6, offset: 2, color: "00000020" } // ❌ CORRUPTS FILE + shadow: { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.12 } // ✅ CORRECT + ``` + +3. **Use `bullet: true`** - NEVER unicode symbols like "•" (creates double bullets) + +4. **Use `breakLine: true`** between array items or text runs together + +5. **Avoid `lineSpacing` with bullets** - causes excessive gaps; use `paraSpaceAfter` instead + +6. **Each presentation needs fresh instance** - don't reuse `pptxgen()` objects + +7. **NEVER reuse option objects across calls** - PptxGenJS mutates objects in-place (e.g. converting shadow values to EMU). Sharing one object between multiple calls corrupts the second shape. + ```javascript + const shadow = { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 }; + slide.addShape(pres.shapes.RECTANGLE, { shadow, ... }); // ❌ second call gets already-converted values + slide.addShape(pres.shapes.RECTANGLE, { shadow, ... }); + + const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.15 }); + slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... }); // ✅ fresh object each time + slide.addShape(pres.shapes.RECTANGLE, { shadow: makeShadow(), ... }); + ``` + +8. **Don't use `ROUNDED_RECTANGLE` with accent borders** - rectangular overlay bars won't cover rounded corners. Use `RECTANGLE` instead. + ```javascript + // ❌ WRONG: Accent bar doesn't cover rounded corners + slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } }); + slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } }); + + // ✅ CORRECT: Use RECTANGLE for clean alignment + slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 3, h: 1.5, fill: { color: "FFFFFF" } }); + slide.addShape(pres.shapes.RECTANGLE, { x: 1, y: 1, w: 0.08, h: 1.5, fill: { color: "0891B2" } }); + ``` + +--- + +## Quick Reference + +- **Shapes**: RECTANGLE, OVAL, LINE, ROUNDED_RECTANGLE +- **Charts**: BAR, LINE, PIE, DOUGHNUT, SCATTER, BUBBLE, RADAR +- **Layouts**: LAYOUT_16x9 (10"×5.625"), LAYOUT_16x10, LAYOUT_4x3, LAYOUT_WIDE +- **Alignment**: "left", "center", "right" +- **Chart data labels**: "outEnd", "inEnd", "center" diff --git a/account/admin/skills/pptx/scripts/__init__.py b/account/admin/skills/pptx/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account/admin/skills/pptx/scripts/add_slide.py b/account/admin/skills/pptx/scripts/add_slide.py new file mode 100644 index 0000000..13700df --- /dev/null +++ b/account/admin/skills/pptx/scripts/add_slide.py @@ -0,0 +1,195 @@ +"""Add a new slide to an unpacked PPTX directory. + +Usage: python add_slide.py + +The source can be: + - A slide file (e.g., slide2.xml) - duplicates the slide + - A layout file (e.g., slideLayout2.xml) - creates from layout + +Examples: + python add_slide.py unpacked/ slide2.xml + # Duplicates slide2, creates slide5.xml + + python add_slide.py unpacked/ slideLayout2.xml + # Creates slide5.xml from slideLayout2.xml + +To see available layouts: ls unpacked/ppt/slideLayouts/ + +Prints the element to add to presentation.xml. +""" + +import re +import shutil +import sys +from pathlib import Path + + +def get_next_slide_number(slides_dir: Path) -> int: + existing = [int(m.group(1)) for f in slides_dir.glob("slide*.xml") + if (m := re.match(r"slide(\d+)\.xml", f.name))] + return max(existing) + 1 if existing else 1 + + +def create_slide_from_layout(unpacked_dir: Path, layout_file: str) -> None: + slides_dir = unpacked_dir / "ppt" / "slides" + rels_dir = slides_dir / "_rels" + layouts_dir = unpacked_dir / "ppt" / "slideLayouts" + + layout_path = layouts_dir / layout_file + if not layout_path.exists(): + print(f"Error: {layout_path} not found", file=sys.stderr) + sys.exit(1) + + next_num = get_next_slide_number(slides_dir) + dest = f"slide{next_num}.xml" + dest_slide = slides_dir / dest + dest_rels = rels_dir / f"{dest}.rels" + + slide_xml = ''' + + + + + + + + + + + + + + + + + + + + + +''' + dest_slide.write_text(slide_xml, encoding="utf-8") + + rels_dir.mkdir(exist_ok=True) + rels_xml = f''' + + +''' + dest_rels.write_text(rels_xml, encoding="utf-8") + + _add_to_content_types(unpacked_dir, dest) + + rid = _add_to_presentation_rels(unpacked_dir, dest) + + next_slide_id = _get_next_slide_id(unpacked_dir) + + print(f"Created {dest} from {layout_file}") + print(f'Add to presentation.xml : ') + + +def duplicate_slide(unpacked_dir: Path, source: str) -> None: + slides_dir = unpacked_dir / "ppt" / "slides" + rels_dir = slides_dir / "_rels" + + source_slide = slides_dir / source + + if not source_slide.exists(): + print(f"Error: {source_slide} not found", file=sys.stderr) + sys.exit(1) + + next_num = get_next_slide_number(slides_dir) + dest = f"slide{next_num}.xml" + dest_slide = slides_dir / dest + + source_rels = rels_dir / f"{source}.rels" + dest_rels = rels_dir / f"{dest}.rels" + + shutil.copy2(source_slide, dest_slide) + + if source_rels.exists(): + shutil.copy2(source_rels, dest_rels) + + rels_content = dest_rels.read_text(encoding="utf-8") + rels_content = re.sub( + r'\s*]*Type="[^"]*notesSlide"[^>]*/>\s*', + "\n", + rels_content, + ) + dest_rels.write_text(rels_content, encoding="utf-8") + + _add_to_content_types(unpacked_dir, dest) + + rid = _add_to_presentation_rels(unpacked_dir, dest) + + next_slide_id = _get_next_slide_id(unpacked_dir) + + print(f"Created {dest} from {source}") + print(f'Add to presentation.xml : ') + + +def _add_to_content_types(unpacked_dir: Path, dest: str) -> None: + content_types_path = unpacked_dir / "[Content_Types].xml" + content_types = content_types_path.read_text(encoding="utf-8") + + new_override = f'' + + if f"/ppt/slides/{dest}" not in content_types: + content_types = content_types.replace("", f" {new_override}\n") + content_types_path.write_text(content_types, encoding="utf-8") + + +def _add_to_presentation_rels(unpacked_dir: Path, dest: str) -> str: + pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels" + pres_rels = pres_rels_path.read_text(encoding="utf-8") + + rids = [int(m) for m in re.findall(r'Id="rId(\d+)"', pres_rels)] + next_rid = max(rids) + 1 if rids else 1 + rid = f"rId{next_rid}" + + new_rel = f'' + + if f"slides/{dest}" not in pres_rels: + pres_rels = pres_rels.replace("", f" {new_rel}\n") + pres_rels_path.write_text(pres_rels, encoding="utf-8") + + return rid + + +def _get_next_slide_id(unpacked_dir: Path) -> int: + pres_path = unpacked_dir / "ppt" / "presentation.xml" + pres_content = pres_path.read_text(encoding="utf-8") + slide_ids = [int(m) for m in re.findall(r']*id="(\d+)"', pres_content)] + return max(slide_ids) + 1 if slide_ids else 256 + + +def parse_source(source: str) -> tuple[str, str | None]: + if source.startswith("slideLayout") and source.endswith(".xml"): + return ("layout", source) + + return ("slide", None) + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: python add_slide.py ", file=sys.stderr) + print("", file=sys.stderr) + print("Source can be:", file=sys.stderr) + print(" slide2.xml - duplicate an existing slide", file=sys.stderr) + print(" slideLayout2.xml - create from a layout template", file=sys.stderr) + print("", file=sys.stderr) + print("To see available layouts: ls /ppt/slideLayouts/", file=sys.stderr) + sys.exit(1) + + unpacked_dir = Path(sys.argv[1]) + source = sys.argv[2] + + if not unpacked_dir.exists(): + print(f"Error: {unpacked_dir} not found", file=sys.stderr) + sys.exit(1) + + source_type, layout_file = parse_source(source) + + if source_type == "layout" and layout_file is not None: + create_slide_from_layout(unpacked_dir, layout_file) + else: + duplicate_slide(unpacked_dir, source) diff --git a/account/admin/skills/pptx/scripts/clean.py b/account/admin/skills/pptx/scripts/clean.py new file mode 100644 index 0000000..3d13994 --- /dev/null +++ b/account/admin/skills/pptx/scripts/clean.py @@ -0,0 +1,286 @@ +"""Remove unreferenced files from an unpacked PPTX directory. + +Usage: python clean.py + +Example: + python clean.py unpacked/ + +This script removes: +- Orphaned slides (not in sldIdLst) and their relationships +- [trash] directory (unreferenced files) +- Orphaned .rels files for deleted resources +- Unreferenced media, embeddings, charts, diagrams, drawings, ink files +- Unreferenced theme files +- Unreferenced notes slides +- Content-Type overrides for deleted files +""" + +import sys +from pathlib import Path + +import defusedxml.minidom + + +import re + + +def get_slides_in_sldidlst(unpacked_dir: Path) -> set[str]: + pres_path = unpacked_dir / "ppt" / "presentation.xml" + pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels" + + if not pres_path.exists() or not pres_rels_path.exists(): + return set() + + rels_dom = defusedxml.minidom.parse(str(pres_rels_path)) + rid_to_slide = {} + for rel in rels_dom.getElementsByTagName("Relationship"): + rid = rel.getAttribute("Id") + target = rel.getAttribute("Target") + rel_type = rel.getAttribute("Type") + if "slide" in rel_type and target.startswith("slides/"): + rid_to_slide[rid] = target.replace("slides/", "") + + pres_content = pres_path.read_text(encoding="utf-8") + referenced_rids = set(re.findall(r']*r:id="([^"]+)"', pres_content)) + + return {rid_to_slide[rid] for rid in referenced_rids if rid in rid_to_slide} + + +def remove_orphaned_slides(unpacked_dir: Path) -> list[str]: + slides_dir = unpacked_dir / "ppt" / "slides" + slides_rels_dir = slides_dir / "_rels" + pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels" + + if not slides_dir.exists(): + return [] + + referenced_slides = get_slides_in_sldidlst(unpacked_dir) + removed = [] + + for slide_file in slides_dir.glob("slide*.xml"): + if slide_file.name not in referenced_slides: + rel_path = slide_file.relative_to(unpacked_dir) + slide_file.unlink() + removed.append(str(rel_path)) + + rels_file = slides_rels_dir / f"{slide_file.name}.rels" + if rels_file.exists(): + rels_file.unlink() + removed.append(str(rels_file.relative_to(unpacked_dir))) + + if removed and pres_rels_path.exists(): + rels_dom = defusedxml.minidom.parse(str(pres_rels_path)) + changed = False + + for rel in list(rels_dom.getElementsByTagName("Relationship")): + target = rel.getAttribute("Target") + if target.startswith("slides/"): + slide_name = target.replace("slides/", "") + if slide_name not in referenced_slides: + if rel.parentNode: + rel.parentNode.removeChild(rel) + changed = True + + if changed: + with open(pres_rels_path, "wb") as f: + f.write(rels_dom.toxml(encoding="utf-8")) + + return removed + + +def remove_trash_directory(unpacked_dir: Path) -> list[str]: + trash_dir = unpacked_dir / "[trash]" + removed = [] + + if trash_dir.exists() and trash_dir.is_dir(): + for file_path in trash_dir.iterdir(): + if file_path.is_file(): + rel_path = file_path.relative_to(unpacked_dir) + removed.append(str(rel_path)) + file_path.unlink() + trash_dir.rmdir() + + return removed + + +def get_slide_referenced_files(unpacked_dir: Path) -> set: + referenced = set() + slides_rels_dir = unpacked_dir / "ppt" / "slides" / "_rels" + + if not slides_rels_dir.exists(): + return referenced + + for rels_file in slides_rels_dir.glob("*.rels"): + dom = defusedxml.minidom.parse(str(rels_file)) + for rel in dom.getElementsByTagName("Relationship"): + target = rel.getAttribute("Target") + if not target: + continue + target_path = (rels_file.parent.parent / target).resolve() + try: + referenced.add(target_path.relative_to(unpacked_dir.resolve())) + except ValueError: + pass + + return referenced + + +def remove_orphaned_rels_files(unpacked_dir: Path) -> list[str]: + resource_dirs = ["charts", "diagrams", "drawings"] + removed = [] + slide_referenced = get_slide_referenced_files(unpacked_dir) + + for dir_name in resource_dirs: + rels_dir = unpacked_dir / "ppt" / dir_name / "_rels" + if not rels_dir.exists(): + continue + + for rels_file in rels_dir.glob("*.rels"): + resource_file = rels_dir.parent / rels_file.name.replace(".rels", "") + try: + resource_rel_path = resource_file.resolve().relative_to(unpacked_dir.resolve()) + except ValueError: + continue + + if not resource_file.exists() or resource_rel_path not in slide_referenced: + rels_file.unlink() + rel_path = rels_file.relative_to(unpacked_dir) + removed.append(str(rel_path)) + + return removed + + +def get_referenced_files(unpacked_dir: Path) -> set: + referenced = set() + + for rels_file in unpacked_dir.rglob("*.rels"): + dom = defusedxml.minidom.parse(str(rels_file)) + for rel in dom.getElementsByTagName("Relationship"): + target = rel.getAttribute("Target") + if not target: + continue + target_path = (rels_file.parent.parent / target).resolve() + try: + referenced.add(target_path.relative_to(unpacked_dir.resolve())) + except ValueError: + pass + + return referenced + + +def remove_orphaned_files(unpacked_dir: Path, referenced: set) -> list[str]: + resource_dirs = ["media", "embeddings", "charts", "diagrams", "tags", "drawings", "ink"] + removed = [] + + for dir_name in resource_dirs: + dir_path = unpacked_dir / "ppt" / dir_name + if not dir_path.exists(): + continue + + for file_path in dir_path.glob("*"): + if not file_path.is_file(): + continue + rel_path = file_path.relative_to(unpacked_dir) + if rel_path not in referenced: + file_path.unlink() + removed.append(str(rel_path)) + + theme_dir = unpacked_dir / "ppt" / "theme" + if theme_dir.exists(): + for file_path in theme_dir.glob("theme*.xml"): + rel_path = file_path.relative_to(unpacked_dir) + if rel_path not in referenced: + file_path.unlink() + removed.append(str(rel_path)) + theme_rels = theme_dir / "_rels" / f"{file_path.name}.rels" + if theme_rels.exists(): + theme_rels.unlink() + removed.append(str(theme_rels.relative_to(unpacked_dir))) + + notes_dir = unpacked_dir / "ppt" / "notesSlides" + if notes_dir.exists(): + for file_path in notes_dir.glob("*.xml"): + if not file_path.is_file(): + continue + rel_path = file_path.relative_to(unpacked_dir) + if rel_path not in referenced: + file_path.unlink() + removed.append(str(rel_path)) + + notes_rels_dir = notes_dir / "_rels" + if notes_rels_dir.exists(): + for file_path in notes_rels_dir.glob("*.rels"): + notes_file = notes_dir / file_path.name.replace(".rels", "") + if not notes_file.exists(): + file_path.unlink() + removed.append(str(file_path.relative_to(unpacked_dir))) + + return removed + + +def update_content_types(unpacked_dir: Path, removed_files: list[str]) -> None: + ct_path = unpacked_dir / "[Content_Types].xml" + if not ct_path.exists(): + return + + dom = defusedxml.minidom.parse(str(ct_path)) + changed = False + + for override in list(dom.getElementsByTagName("Override")): + part_name = override.getAttribute("PartName").lstrip("/") + if part_name in removed_files: + if override.parentNode: + override.parentNode.removeChild(override) + changed = True + + if changed: + with open(ct_path, "wb") as f: + f.write(dom.toxml(encoding="utf-8")) + + +def clean_unused_files(unpacked_dir: Path) -> list[str]: + all_removed = [] + + slides_removed = remove_orphaned_slides(unpacked_dir) + all_removed.extend(slides_removed) + + trash_removed = remove_trash_directory(unpacked_dir) + all_removed.extend(trash_removed) + + while True: + removed_rels = remove_orphaned_rels_files(unpacked_dir) + referenced = get_referenced_files(unpacked_dir) + removed_files = remove_orphaned_files(unpacked_dir, referenced) + + total_removed = removed_rels + removed_files + if not total_removed: + break + + all_removed.extend(total_removed) + + if all_removed: + update_content_types(unpacked_dir, all_removed) + + return all_removed + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python clean.py ", file=sys.stderr) + print("Example: python clean.py unpacked/", file=sys.stderr) + sys.exit(1) + + unpacked_dir = Path(sys.argv[1]) + + if not unpacked_dir.exists(): + print(f"Error: {unpacked_dir} not found", file=sys.stderr) + sys.exit(1) + + removed = clean_unused_files(unpacked_dir) + + if removed: + print(f"Removed {len(removed)} unreferenced files:") + for f in removed: + print(f" {f}") + else: + print("No unreferenced files found") diff --git a/account/admin/skills/pptx/scripts/html2pptx.js b/account/admin/skills/pptx/scripts/html2pptx.js new file mode 100644 index 0000000..437bf7c --- /dev/null +++ b/account/admin/skills/pptx/scripts/html2pptx.js @@ -0,0 +1,979 @@ +/** + * html2pptx - Convert HTML slide to pptxgenjs slide with positioned elements + * + * USAGE: + * const pptx = new pptxgen(); + * pptx.layout = 'LAYOUT_16x9'; // Must match HTML body dimensions + * + * const { slide, placeholders } = await html2pptx('slide.html', pptx); + * slide.addChart(pptx.charts.LINE, data, placeholders[0]); + * + * await pptx.writeFile('output.pptx'); + * + * FEATURES: + * - Converts HTML to PowerPoint with accurate positioning + * - Supports text, images, shapes, and bullet lists + * - Extracts placeholder elements (class="placeholder") with positions + * - Handles CSS gradients, borders, and margins + * + * VALIDATION: + * - Uses body width/height from HTML for viewport sizing + * - Throws error if HTML dimensions don't match presentation layout + * - Throws error if content overflows body (with overflow details) + * + * RETURNS: + * { slide, placeholders } where placeholders is an array of { id, x, y, w, h } + */ + +const { chromium } = require('playwright'); +const path = require('path'); +const sharp = require('sharp'); + +const PT_PER_PX = 0.75; +const PX_PER_IN = 96; +const EMU_PER_IN = 914400; + +// Helper: Get body dimensions and check for overflow +async function getBodyDimensions(page) { + const bodyDimensions = await page.evaluate(() => { + const body = document.body; + const style = window.getComputedStyle(body); + + return { + width: parseFloat(style.width), + height: parseFloat(style.height), + scrollWidth: body.scrollWidth, + scrollHeight: body.scrollHeight + }; + }); + + const errors = []; + const widthOverflowPx = Math.max(0, bodyDimensions.scrollWidth - bodyDimensions.width - 1); + const heightOverflowPx = Math.max(0, bodyDimensions.scrollHeight - bodyDimensions.height - 1); + + const widthOverflowPt = widthOverflowPx * PT_PER_PX; + const heightOverflowPt = heightOverflowPx * PT_PER_PX; + + if (widthOverflowPt > 0 || heightOverflowPt > 0) { + const directions = []; + if (widthOverflowPt > 0) directions.push(`${widthOverflowPt.toFixed(1)}pt horizontally`); + if (heightOverflowPt > 0) directions.push(`${heightOverflowPt.toFixed(1)}pt vertically`); + const reminder = heightOverflowPt > 0 ? ' (Remember: leave 0.5" margin at bottom of slide)' : ''; + errors.push(`HTML content overflows body by ${directions.join(' and ')}${reminder}`); + } + + return { ...bodyDimensions, errors }; +} + +// Helper: Validate dimensions match presentation layout +function validateDimensions(bodyDimensions, pres) { + const errors = []; + const widthInches = bodyDimensions.width / PX_PER_IN; + const heightInches = bodyDimensions.height / PX_PER_IN; + + if (pres.presLayout) { + const layoutWidth = pres.presLayout.width / EMU_PER_IN; + const layoutHeight = pres.presLayout.height / EMU_PER_IN; + + if (Math.abs(layoutWidth - widthInches) > 0.1 || Math.abs(layoutHeight - heightInches) > 0.1) { + errors.push( + `HTML dimensions (${widthInches.toFixed(1)}" × ${heightInches.toFixed(1)}") ` + + `don't match presentation layout (${layoutWidth.toFixed(1)}" × ${layoutHeight.toFixed(1)}")` + ); + } + } + return errors; +} + +function validateTextBoxPosition(slideData, bodyDimensions) { + const errors = []; + const slideHeightInches = bodyDimensions.height / PX_PER_IN; + const minBottomMargin = 0.5; // 0.5 inches from bottom + + for (const el of slideData.elements) { + // Check text elements (p, h1-h6, list) + if (['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'list'].includes(el.type)) { + const fontSize = el.style?.fontSize || 0; + const bottomEdge = el.position.y + el.position.h; + const distanceFromBottom = slideHeightInches - bottomEdge; + + if (fontSize > 12 && distanceFromBottom < minBottomMargin) { + const getText = () => { + if (typeof el.text === 'string') return el.text; + if (Array.isArray(el.text)) return el.text.find(t => t.text)?.text || ''; + if (Array.isArray(el.items)) return el.items.find(item => item.text)?.text || ''; + return ''; + }; + const textPrefix = getText().substring(0, 50) + (getText().length > 50 ? '...' : ''); + + errors.push( + `Text box "${textPrefix}" ends too close to bottom edge ` + + `(${distanceFromBottom.toFixed(2)}" from bottom, minimum ${minBottomMargin}" required)` + ); + } + } + } + + return errors; +} + +// Helper: Add background to slide +async function addBackground(slideData, targetSlide, tmpDir) { + if (slideData.background.type === 'image' && slideData.background.path) { + let imagePath = slideData.background.path.startsWith('file://') + ? slideData.background.path.replace('file://', '') + : slideData.background.path; + targetSlide.background = { path: imagePath }; + } else if (slideData.background.type === 'color' && slideData.background.value) { + targetSlide.background = { color: slideData.background.value }; + } +} + +// Helper: Add elements to slide +function addElements(slideData, targetSlide, pres) { + for (const el of slideData.elements) { + if (el.type === 'image') { + let imagePath = el.src.startsWith('file://') ? el.src.replace('file://', '') : el.src; + targetSlide.addImage({ + path: imagePath, + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h + }); + } else if (el.type === 'line') { + targetSlide.addShape(pres.ShapeType.line, { + x: el.x1, + y: el.y1, + w: el.x2 - el.x1, + h: el.y2 - el.y1, + line: { color: el.color, width: el.width } + }); + } else if (el.type === 'shape') { + const shapeOptions = { + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h, + shape: el.shape.rectRadius > 0 ? pres.ShapeType.roundRect : pres.ShapeType.rect + }; + + if (el.shape.fill) { + shapeOptions.fill = { color: el.shape.fill }; + if (el.shape.transparency != null) shapeOptions.fill.transparency = el.shape.transparency; + } + if (el.shape.line) shapeOptions.line = el.shape.line; + if (el.shape.rectRadius > 0) shapeOptions.rectRadius = el.shape.rectRadius; + if (el.shape.shadow) shapeOptions.shadow = el.shape.shadow; + + targetSlide.addText(el.text || '', shapeOptions); + } else if (el.type === 'list') { + const listOptions = { + x: el.position.x, + y: el.position.y, + w: el.position.w, + h: el.position.h, + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + align: el.style.align, + valign: 'top', + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + margin: el.style.margin + }; + if (el.style.margin) listOptions.margin = el.style.margin; + targetSlide.addText(el.items, listOptions); + } else { + // Check if text is single-line (height suggests one line) + const lineHeight = el.style.lineSpacing || el.style.fontSize * 1.2; + const isSingleLine = el.position.h <= lineHeight * 1.5; + + let adjustedX = el.position.x; + let adjustedW = el.position.w; + + // Make single-line text 2% wider to account for underestimate + if (isSingleLine) { + const widthIncrease = el.position.w * 0.02; + const align = el.style.align; + + if (align === 'center') { + // Center: expand both sides + adjustedX = el.position.x - (widthIncrease / 2); + adjustedW = el.position.w + widthIncrease; + } else if (align === 'right') { + // Right: expand to the left + adjustedX = el.position.x - widthIncrease; + adjustedW = el.position.w + widthIncrease; + } else { + // Left (default): expand to the right + adjustedW = el.position.w + widthIncrease; + } + } + + const textOptions = { + x: adjustedX, + y: el.position.y, + w: adjustedW, + h: el.position.h, + fontSize: el.style.fontSize, + fontFace: el.style.fontFace, + color: el.style.color, + bold: el.style.bold, + italic: el.style.italic, + underline: el.style.underline, + valign: 'top', + lineSpacing: el.style.lineSpacing, + paraSpaceBefore: el.style.paraSpaceBefore, + paraSpaceAfter: el.style.paraSpaceAfter, + inset: 0 // Remove default PowerPoint internal padding + }; + + if (el.style.align) textOptions.align = el.style.align; + if (el.style.margin) textOptions.margin = el.style.margin; + if (el.style.rotate !== undefined) textOptions.rotate = el.style.rotate; + if (el.style.transparency !== null && el.style.transparency !== undefined) textOptions.transparency = el.style.transparency; + + targetSlide.addText(el.text, textOptions); + } + } +} + +// Helper: Extract slide data from HTML page +async function extractSlideData(page) { + return await page.evaluate(() => { + const PT_PER_PX = 0.75; + const PX_PER_IN = 96; + + // Fonts that are single-weight and should not have bold applied + // (applying bold causes PowerPoint to use faux bold which makes text wider) + const SINGLE_WEIGHT_FONTS = ['impact']; + + // Helper: Check if a font should skip bold formatting + const shouldSkipBold = (fontFamily) => { + if (!fontFamily) return false; + const normalizedFont = fontFamily.toLowerCase().replace(/['"]/g, '').split(',')[0].trim(); + return SINGLE_WEIGHT_FONTS.includes(normalizedFont); + }; + + // Unit conversion helpers + const pxToInch = (px) => px / PX_PER_IN; + const pxToPoints = (pxStr) => parseFloat(pxStr) * PT_PER_PX; + const rgbToHex = (rgbStr) => { + // Handle transparent backgrounds by defaulting to white + if (rgbStr === 'rgba(0, 0, 0, 0)' || rgbStr === 'transparent') return 'FFFFFF'; + + const match = rgbStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); + if (!match) return 'FFFFFF'; + return match.slice(1).map(n => parseInt(n).toString(16).padStart(2, '0')).join(''); + }; + + const extractAlpha = (rgbStr) => { + const match = rgbStr.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/); + if (!match || !match[4]) return null; + const alpha = parseFloat(match[4]); + return Math.round((1 - alpha) * 100); + }; + + const applyTextTransform = (text, textTransform) => { + if (textTransform === 'uppercase') return text.toUpperCase(); + if (textTransform === 'lowercase') return text.toLowerCase(); + if (textTransform === 'capitalize') { + return text.replace(/\b\w/g, c => c.toUpperCase()); + } + return text; + }; + + // Extract rotation angle from CSS transform and writing-mode + const getRotation = (transform, writingMode) => { + let angle = 0; + + // Handle writing-mode first + // PowerPoint: 90° = text rotated 90° clockwise (reads top to bottom, letters upright) + // PowerPoint: 270° = text rotated 270° clockwise (reads bottom to top, letters upright) + if (writingMode === 'vertical-rl') { + // vertical-rl alone = text reads top to bottom = 90° in PowerPoint + angle = 90; + } else if (writingMode === 'vertical-lr') { + // vertical-lr alone = text reads bottom to top = 270° in PowerPoint + angle = 270; + } + + // Then add any transform rotation + if (transform && transform !== 'none') { + // Try to match rotate() function + const rotateMatch = transform.match(/rotate\((-?\d+(?:\.\d+)?)deg\)/); + if (rotateMatch) { + angle += parseFloat(rotateMatch[1]); + } else { + // Browser may compute as matrix - extract rotation from matrix + const matrixMatch = transform.match(/matrix\(([^)]+)\)/); + if (matrixMatch) { + const values = matrixMatch[1].split(',').map(parseFloat); + // matrix(a, b, c, d, e, f) where rotation = atan2(b, a) + const matrixAngle = Math.atan2(values[1], values[0]) * (180 / Math.PI); + angle += Math.round(matrixAngle); + } + } + } + + // Normalize to 0-359 range + angle = angle % 360; + if (angle < 0) angle += 360; + + return angle === 0 ? null : angle; + }; + + // Get position/dimensions accounting for rotation + const getPositionAndSize = (el, rect, rotation) => { + if (rotation === null) { + return { x: rect.left, y: rect.top, w: rect.width, h: rect.height }; + } + + // For 90° or 270° rotations, swap width and height + // because PowerPoint applies rotation to the original (unrotated) box + const isVertical = rotation === 90 || rotation === 270; + + if (isVertical) { + // The browser shows us the rotated dimensions (tall box for vertical text) + // But PowerPoint needs the pre-rotation dimensions (wide box that will be rotated) + // So we swap: browser's height becomes PPT's width, browser's width becomes PPT's height + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + + return { + x: centerX - rect.height / 2, + y: centerY - rect.width / 2, + w: rect.height, + h: rect.width + }; + } + + // For other rotations, use element's offset dimensions + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + return { + x: centerX - el.offsetWidth / 2, + y: centerY - el.offsetHeight / 2, + w: el.offsetWidth, + h: el.offsetHeight + }; + }; + + // Parse CSS box-shadow into PptxGenJS shadow properties + const parseBoxShadow = (boxShadow) => { + if (!boxShadow || boxShadow === 'none') return null; + + // Browser computed style format: "rgba(0, 0, 0, 0.3) 2px 2px 8px 0px [inset]" + // CSS format: "[inset] 2px 2px 8px 0px rgba(0, 0, 0, 0.3)" + + const insetMatch = boxShadow.match(/inset/); + + // IMPORTANT: PptxGenJS/PowerPoint doesn't properly support inset shadows + // Only process outer shadows to avoid file corruption + if (insetMatch) return null; + + // Extract color first (rgba or rgb at start) + const colorMatch = boxShadow.match(/rgba?\([^)]+\)/); + + // Extract numeric values (handles both px and pt units) + const parts = boxShadow.match(/([-\d.]+)(px|pt)/g); + + if (!parts || parts.length < 2) return null; + + const offsetX = parseFloat(parts[0]); + const offsetY = parseFloat(parts[1]); + const blur = parts.length > 2 ? parseFloat(parts[2]) : 0; + + // Calculate angle from offsets (in degrees, 0 = right, 90 = down) + let angle = 0; + if (offsetX !== 0 || offsetY !== 0) { + angle = Math.atan2(offsetY, offsetX) * (180 / Math.PI); + if (angle < 0) angle += 360; + } + + // Calculate offset distance (hypotenuse) + const offset = Math.sqrt(offsetX * offsetX + offsetY * offsetY) * PT_PER_PX; + + // Extract opacity from rgba + let opacity = 0.5; + if (colorMatch) { + const opacityMatch = colorMatch[0].match(/[\d.]+\)$/); + if (opacityMatch) { + opacity = parseFloat(opacityMatch[0].replace(')', '')); + } + } + + return { + type: 'outer', + angle: Math.round(angle), + blur: blur * 0.75, // Convert to points + color: colorMatch ? rgbToHex(colorMatch[0]) : '000000', + offset: offset, + opacity + }; + }; + + // Parse inline formatting tags (, , , , , ) into text runs + const parseInlineFormatting = (element, baseOptions = {}, runs = [], baseTextTransform = (x) => x) => { + let prevNodeIsText = false; + + element.childNodes.forEach((node) => { + let textTransform = baseTextTransform; + + const isText = node.nodeType === Node.TEXT_NODE || node.tagName === 'BR'; + if (isText) { + const text = node.tagName === 'BR' ? '\n' : textTransform(node.textContent.replace(/\s+/g, ' ')); + const prevRun = runs[runs.length - 1]; + if (prevNodeIsText && prevRun) { + prevRun.text += text; + } else { + runs.push({ text, options: { ...baseOptions } }); + } + + } else if (node.nodeType === Node.ELEMENT_NODE && node.textContent.trim()) { + const options = { ...baseOptions }; + const computed = window.getComputedStyle(node); + + // Handle inline elements with computed styles + if (node.tagName === 'SPAN' || node.tagName === 'B' || node.tagName === 'STRONG' || node.tagName === 'I' || node.tagName === 'EM' || node.tagName === 'U') { + const isBold = computed.fontWeight === 'bold' || parseInt(computed.fontWeight) >= 600; + if (isBold && !shouldSkipBold(computed.fontFamily)) options.bold = true; + if (computed.fontStyle === 'italic') options.italic = true; + if (computed.textDecoration && computed.textDecoration.includes('underline')) options.underline = true; + if (computed.color && computed.color !== 'rgb(0, 0, 0)') { + options.color = rgbToHex(computed.color); + const transparency = extractAlpha(computed.color); + if (transparency !== null) options.transparency = transparency; + } + if (computed.fontSize) options.fontSize = pxToPoints(computed.fontSize); + + // Apply text-transform on the span element itself + if (computed.textTransform && computed.textTransform !== 'none') { + const transformStr = computed.textTransform; + textTransform = (text) => applyTextTransform(text, transformStr); + } + + // Validate: Check for margins on inline elements + if (computed.marginLeft && parseFloat(computed.marginLeft) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-left which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginRight && parseFloat(computed.marginRight) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-right which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginTop && parseFloat(computed.marginTop) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-top which is not supported in PowerPoint. Remove margin from inline elements.`); + } + if (computed.marginBottom && parseFloat(computed.marginBottom) > 0) { + errors.push(`Inline element <${node.tagName.toLowerCase()}> has margin-bottom which is not supported in PowerPoint. Remove margin from inline elements.`); + } + + // Recursively process the child node. This will flatten nested spans into multiple runs. + parseInlineFormatting(node, options, runs, textTransform); + } + } + + prevNodeIsText = isText; + }); + + // Trim leading space from first run and trailing space from last run + if (runs.length > 0) { + runs[0].text = runs[0].text.replace(/^\s+/, ''); + runs[runs.length - 1].text = runs[runs.length - 1].text.replace(/\s+$/, ''); + } + + return runs.filter(r => r.text.length > 0); + }; + + // Extract background from body (image or color) + const body = document.body; + const bodyStyle = window.getComputedStyle(body); + const bgImage = bodyStyle.backgroundImage; + const bgColor = bodyStyle.backgroundColor; + + // Collect validation errors + const errors = []; + + // Validate: Check for CSS gradients + if (bgImage && (bgImage.includes('linear-gradient') || bgImage.includes('radial-gradient'))) { + errors.push( + 'CSS gradients are not supported. Use Sharp to rasterize gradients as PNG images first, ' + + 'then reference with background-image: url(\'gradient.png\')' + ); + } + + let background; + if (bgImage && bgImage !== 'none') { + // Extract URL from url("...") or url(...) + const urlMatch = bgImage.match(/url\(["']?([^"')]+)["']?\)/); + if (urlMatch) { + background = { + type: 'image', + path: urlMatch[1] + }; + } else { + background = { + type: 'color', + value: rgbToHex(bgColor) + }; + } + } else { + background = { + type: 'color', + value: rgbToHex(bgColor) + }; + } + + // Process all elements + const elements = []; + const placeholders = []; + const textTags = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'LI']; + const processed = new Set(); + + document.querySelectorAll('*').forEach((el) => { + if (processed.has(el)) return; + + // Validate text elements don't have backgrounds, borders, or shadows + if (textTags.includes(el.tagName)) { + const computed = window.getComputedStyle(el); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + const hasBorder = (computed.borderWidth && parseFloat(computed.borderWidth) > 0) || + (computed.borderTopWidth && parseFloat(computed.borderTopWidth) > 0) || + (computed.borderRightWidth && parseFloat(computed.borderRightWidth) > 0) || + (computed.borderBottomWidth && parseFloat(computed.borderBottomWidth) > 0) || + (computed.borderLeftWidth && parseFloat(computed.borderLeftWidth) > 0); + const hasShadow = computed.boxShadow && computed.boxShadow !== 'none'; + + if (hasBg || hasBorder || hasShadow) { + errors.push( + `Text element <${el.tagName.toLowerCase()}> has ${hasBg ? 'background' : hasBorder ? 'border' : 'shadow'}. ` + + 'Backgrounds, borders, and shadows are only supported on
                  elements, not text elements.' + ); + return; + } + } + + // Extract placeholder elements (for charts, etc.) + if (el.className && el.className.includes('placeholder')) { + const rect = el.getBoundingClientRect(); + if (rect.width === 0 || rect.height === 0) { + errors.push( + `Placeholder "${el.id || 'unnamed'}" has ${rect.width === 0 ? 'width: 0' : 'height: 0'}. Check the layout CSS.` + ); + } else { + placeholders.push({ + id: el.id || `placeholder-${placeholders.length}`, + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + }); + } + processed.add(el); + return; + } + + // Extract images + if (el.tagName === 'IMG') { + const rect = el.getBoundingClientRect(); + if (rect.width > 0 && rect.height > 0) { + elements.push({ + type: 'image', + src: el.src, + position: { + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + } + }); + processed.add(el); + return; + } + } + + // Extract DIVs with backgrounds/borders as shapes + const isContainer = el.tagName === 'DIV' && !textTags.includes(el.tagName); + if (isContainer) { + const computed = window.getComputedStyle(el); + const hasBg = computed.backgroundColor && computed.backgroundColor !== 'rgba(0, 0, 0, 0)'; + + // Validate: Check for unwrapped text content in DIV + for (const node of el.childNodes) { + if (node.nodeType === Node.TEXT_NODE) { + const text = node.textContent.trim(); + if (text) { + errors.push( + `DIV element contains unwrapped text "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}". ` + + 'All text must be wrapped in

                  ,

                  -

                  ,
                    , or
                      tags to appear in PowerPoint.' + ); + } + } + } + + // Check for background images on shapes + const bgImage = computed.backgroundImage; + if (bgImage && bgImage !== 'none') { + errors.push( + 'Background images on DIV elements are not supported. ' + + 'Use solid colors or borders for shapes, or use slide.addImage() in PptxGenJS to layer images.' + ); + return; + } + + // Check for borders - both uniform and partial + const borderTop = computed.borderTopWidth; + const borderRight = computed.borderRightWidth; + const borderBottom = computed.borderBottomWidth; + const borderLeft = computed.borderLeftWidth; + const borders = [borderTop, borderRight, borderBottom, borderLeft].map(b => parseFloat(b) || 0); + const hasBorder = borders.some(b => b > 0); + const hasUniformBorder = hasBorder && borders.every(b => b === borders[0]); + const borderLines = []; + + if (hasBorder && !hasUniformBorder) { + const rect = el.getBoundingClientRect(); + const x = pxToInch(rect.left); + const y = pxToInch(rect.top); + const w = pxToInch(rect.width); + const h = pxToInch(rect.height); + + // Collect lines to add after shape (inset by half the line width to center on edge) + if (parseFloat(borderTop) > 0) { + const widthPt = pxToPoints(borderTop); + const inset = (widthPt / 72) / 2; // Convert points to inches, then half + borderLines.push({ + type: 'line', + x1: x, y1: y + inset, x2: x + w, y2: y + inset, + width: widthPt, + color: rgbToHex(computed.borderTopColor) + }); + } + if (parseFloat(borderRight) > 0) { + const widthPt = pxToPoints(borderRight); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x + w - inset, y1: y, x2: x + w - inset, y2: y + h, + width: widthPt, + color: rgbToHex(computed.borderRightColor) + }); + } + if (parseFloat(borderBottom) > 0) { + const widthPt = pxToPoints(borderBottom); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x, y1: y + h - inset, x2: x + w, y2: y + h - inset, + width: widthPt, + color: rgbToHex(computed.borderBottomColor) + }); + } + if (parseFloat(borderLeft) > 0) { + const widthPt = pxToPoints(borderLeft); + const inset = (widthPt / 72) / 2; + borderLines.push({ + type: 'line', + x1: x + inset, y1: y, x2: x + inset, y2: y + h, + width: widthPt, + color: rgbToHex(computed.borderLeftColor) + }); + } + } + + if (hasBg || hasBorder) { + const rect = el.getBoundingClientRect(); + if (rect.width > 0 && rect.height > 0) { + const shadow = parseBoxShadow(computed.boxShadow); + + // Only add shape if there's background or uniform border + if (hasBg || hasUniformBorder) { + elements.push({ + type: 'shape', + text: '', // Shape only - child text elements render on top + position: { + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + }, + shape: { + fill: hasBg ? rgbToHex(computed.backgroundColor) : null, + transparency: hasBg ? extractAlpha(computed.backgroundColor) : null, + line: hasUniformBorder ? { + color: rgbToHex(computed.borderColor), + width: pxToPoints(computed.borderWidth) + } : null, + // Convert border-radius to rectRadius (in inches) + // % values: 50%+ = circle (1), <50% = percentage of min dimension + // pt values: divide by 72 (72pt = 1 inch) + // px values: divide by 96 (96px = 1 inch) + rectRadius: (() => { + const radius = computed.borderRadius; + const radiusValue = parseFloat(radius); + if (radiusValue === 0) return 0; + + if (radius.includes('%')) { + if (radiusValue >= 50) return 1; + // Calculate percentage of smaller dimension + const minDim = Math.min(rect.width, rect.height); + return (radiusValue / 100) * pxToInch(minDim); + } + + if (radius.includes('pt')) return radiusValue / 72; + return radiusValue / PX_PER_IN; + })(), + shadow: shadow + } + }); + } + + // Add partial border lines + elements.push(...borderLines); + + processed.add(el); + return; + } + } + } + + // Extract bullet lists as single text block + if (el.tagName === 'UL' || el.tagName === 'OL') { + const rect = el.getBoundingClientRect(); + if (rect.width === 0 || rect.height === 0) return; + + const liElements = Array.from(el.querySelectorAll('li')); + const items = []; + const ulComputed = window.getComputedStyle(el); + const ulPaddingLeftPt = pxToPoints(ulComputed.paddingLeft); + + // Split: margin-left for bullet position, indent for text position + // margin-left + indent = ul padding-left + const marginLeft = ulPaddingLeftPt * 0.5; + const textIndent = ulPaddingLeftPt * 0.5; + + liElements.forEach((li, idx) => { + const isLast = idx === liElements.length - 1; + const runs = parseInlineFormatting(li, { breakLine: false }); + // Clean manual bullets from first run + if (runs.length > 0) { + runs[0].text = runs[0].text.replace(/^[•\-\*▪▸]\s*/, ''); + runs[0].options.bullet = { indent: textIndent }; + } + // Set breakLine on last run + if (runs.length > 0 && !isLast) { + runs[runs.length - 1].options.breakLine = true; + } + items.push(...runs); + }); + + const computed = window.getComputedStyle(liElements[0] || el); + + elements.push({ + type: 'list', + items: items, + position: { + x: pxToInch(rect.left), + y: pxToInch(rect.top), + w: pxToInch(rect.width), + h: pxToInch(rect.height) + }, + style: { + fontSize: pxToPoints(computed.fontSize), + fontFace: computed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(), + color: rgbToHex(computed.color), + transparency: extractAlpha(computed.color), + align: computed.textAlign === 'start' ? 'left' : computed.textAlign, + lineSpacing: computed.lineHeight && computed.lineHeight !== 'normal' ? pxToPoints(computed.lineHeight) : null, + paraSpaceBefore: 0, + paraSpaceAfter: pxToPoints(computed.marginBottom), + // PptxGenJS margin array is [left, right, bottom, top] + margin: [marginLeft, 0, 0, 0] + } + }); + + liElements.forEach(li => processed.add(li)); + processed.add(el); + return; + } + + // Extract text elements (P, H1, H2, etc.) + if (!textTags.includes(el.tagName)) return; + + const rect = el.getBoundingClientRect(); + const text = el.textContent.trim(); + if (rect.width === 0 || rect.height === 0 || !text) return; + + // Validate: Check for manual bullet symbols in text elements (not in lists) + if (el.tagName !== 'LI' && /^[•\-\*▪▸○●◆◇■□]\s/.test(text.trimStart())) { + errors.push( + `Text element <${el.tagName.toLowerCase()}> starts with bullet symbol "${text.substring(0, 20)}...". ` + + 'Use
                        or
                          lists instead of manual bullet symbols.' + ); + return; + } + + const computed = window.getComputedStyle(el); + const rotation = getRotation(computed.transform, computed.writingMode); + const { x, y, w, h } = getPositionAndSize(el, rect, rotation); + + const baseStyle = { + fontSize: pxToPoints(computed.fontSize), + fontFace: computed.fontFamily.split(',')[0].replace(/['"]/g, '').trim(), + color: rgbToHex(computed.color), + align: computed.textAlign === 'start' ? 'left' : computed.textAlign, + lineSpacing: pxToPoints(computed.lineHeight), + paraSpaceBefore: pxToPoints(computed.marginTop), + paraSpaceAfter: pxToPoints(computed.marginBottom), + // PptxGenJS margin array is [left, right, bottom, top] (not [top, right, bottom, left] as documented) + margin: [ + pxToPoints(computed.paddingLeft), + pxToPoints(computed.paddingRight), + pxToPoints(computed.paddingBottom), + pxToPoints(computed.paddingTop) + ] + }; + + const transparency = extractAlpha(computed.color); + if (transparency !== null) baseStyle.transparency = transparency; + + if (rotation !== null) baseStyle.rotate = rotation; + + const hasFormatting = el.querySelector('b, i, u, strong, em, span, br'); + + if (hasFormatting) { + // Text with inline formatting + const transformStr = computed.textTransform; + const runs = parseInlineFormatting(el, {}, [], (str) => applyTextTransform(str, transformStr)); + + // Adjust lineSpacing based on largest fontSize in runs + const adjustedStyle = { ...baseStyle }; + if (adjustedStyle.lineSpacing) { + const maxFontSize = Math.max( + adjustedStyle.fontSize, + ...runs.map(r => r.options?.fontSize || 0) + ); + if (maxFontSize > adjustedStyle.fontSize) { + const lineHeightMultiplier = adjustedStyle.lineSpacing / adjustedStyle.fontSize; + adjustedStyle.lineSpacing = maxFontSize * lineHeightMultiplier; + } + } + + elements.push({ + type: el.tagName.toLowerCase(), + text: runs, + position: { x: pxToInch(x), y: pxToInch(y), w: pxToInch(w), h: pxToInch(h) }, + style: adjustedStyle + }); + } else { + // Plain text - inherit CSS formatting + const textTransform = computed.textTransform; + const transformedText = applyTextTransform(text, textTransform); + + const isBold = computed.fontWeight === 'bold' || parseInt(computed.fontWeight) >= 600; + + elements.push({ + type: el.tagName.toLowerCase(), + text: transformedText, + position: { x: pxToInch(x), y: pxToInch(y), w: pxToInch(w), h: pxToInch(h) }, + style: { + ...baseStyle, + bold: isBold && !shouldSkipBold(computed.fontFamily), + italic: computed.fontStyle === 'italic', + underline: computed.textDecoration.includes('underline') + } + }); + } + + processed.add(el); + }); + + return { background, elements, placeholders, errors }; + }); +} + +async function html2pptx(htmlFile, pres, options = {}) { + const { + tmpDir = process.env.TMPDIR || '/tmp', + slide = null + } = options; + + try { + // Use Chrome on macOS, default Chromium on Unix + const launchOptions = { env: { TMPDIR: tmpDir } }; + if (process.platform === 'darwin') { + launchOptions.channel = 'chrome'; + } + + const browser = await chromium.launch(launchOptions); + + let bodyDimensions; + let slideData; + + const filePath = path.isAbsolute(htmlFile) ? htmlFile : path.join(process.cwd(), htmlFile); + const validationErrors = []; + + try { + const page = await browser.newPage(); + page.on('console', (msg) => { + // Log the message text to your test runner's console + console.log(`Browser console: ${msg.text()}`); + }); + + await page.goto(`file://${filePath}`); + + bodyDimensions = await getBodyDimensions(page); + + await page.setViewportSize({ + width: Math.round(bodyDimensions.width), + height: Math.round(bodyDimensions.height) + }); + + slideData = await extractSlideData(page); + } finally { + await browser.close(); + } + + // Collect all validation errors + if (bodyDimensions.errors && bodyDimensions.errors.length > 0) { + validationErrors.push(...bodyDimensions.errors); + } + + const dimensionErrors = validateDimensions(bodyDimensions, pres); + if (dimensionErrors.length > 0) { + validationErrors.push(...dimensionErrors); + } + + const textBoxPositionErrors = validateTextBoxPosition(slideData, bodyDimensions); + if (textBoxPositionErrors.length > 0) { + validationErrors.push(...textBoxPositionErrors); + } + + if (slideData.errors && slideData.errors.length > 0) { + validationErrors.push(...slideData.errors); + } + + // Throw all errors at once if any exist + if (validationErrors.length > 0) { + const errorMessage = validationErrors.length === 1 + ? validationErrors[0] + : `Multiple validation errors found:\n${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join('\n')}`; + throw new Error(errorMessage); + } + + const targetSlide = slide || pres.addSlide(); + + await addBackground(slideData, targetSlide, tmpDir); + addElements(slideData, targetSlide, pres); + + return { slide: targetSlide, placeholders: slideData.placeholders }; + } catch (error) { + if (!error.message.startsWith(htmlFile)) { + throw new Error(`${htmlFile}: ${error.message}`); + } + throw error; + } +} + +module.exports = html2pptx; \ No newline at end of file diff --git a/account/admin/skills/pptx/scripts/inventory.py b/account/admin/skills/pptx/scripts/inventory.py new file mode 100644 index 0000000..edda390 --- /dev/null +++ b/account/admin/skills/pptx/scripts/inventory.py @@ -0,0 +1,1020 @@ +#!/usr/bin/env python3 +""" +Extract structured text content from PowerPoint presentations. + +This module provides functionality to: +- Extract all text content from PowerPoint shapes +- Preserve paragraph formatting (alignment, bullets, fonts, spacing) +- Handle nested GroupShapes recursively with correct absolute positions +- Sort shapes by visual position on slides +- Filter out slide numbers and non-content placeholders +- Export to JSON with clean, structured data + +Classes: + ParagraphData: Represents a text paragraph with formatting + ShapeData: Represents a shape with position and text content + +Main Functions: + extract_text_inventory: Extract all text from a presentation + save_inventory: Save extracted data to JSON + +Usage: + python inventory.py input.pptx output.json +""" + +import argparse +import json +import platform +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple, Union + +from PIL import Image, ImageDraw, ImageFont +from pptx import Presentation +from pptx.enum.text import PP_ALIGN +from pptx.shapes.base import BaseShape + +# Type aliases for cleaner signatures +JsonValue = Union[str, int, float, bool, None] +ParagraphDict = Dict[str, JsonValue] +ShapeDict = Dict[ + str, Union[str, float, bool, List[ParagraphDict], List[str], Dict[str, Any], None] +] +InventoryData = Dict[ + str, Dict[str, "ShapeData"] +] # Dict of slide_id -> {shape_id -> ShapeData} +InventoryDict = Dict[str, Dict[str, ShapeDict]] # JSON-serializable inventory + + +def main(): + """Main entry point for command-line usage.""" + parser = argparse.ArgumentParser( + description="Extract text inventory from PowerPoint with proper GroupShape support.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python inventory.py presentation.pptx inventory.json + Extracts text inventory with correct absolute positions for grouped shapes + + python inventory.py presentation.pptx inventory.json --issues-only + Extracts only text shapes that have overflow or overlap issues + +The output JSON includes: + - All text content organized by slide and shape + - Correct absolute positions for shapes in groups + - Visual position and size in inches + - Paragraph properties and formatting + - Issue detection: text overflow and shape overlaps + """, + ) + + parser.add_argument("input", help="Input PowerPoint file (.pptx)") + parser.add_argument("output", help="Output JSON file for inventory") + parser.add_argument( + "--issues-only", + action="store_true", + help="Include only text shapes that have overflow or overlap issues", + ) + + args = parser.parse_args() + + input_path = Path(args.input) + if not input_path.exists(): + print(f"Error: Input file not found: {args.input}") + sys.exit(1) + + if not input_path.suffix.lower() == ".pptx": + print("Error: Input must be a PowerPoint file (.pptx)") + sys.exit(1) + + try: + print(f"Extracting text inventory from: {args.input}") + if args.issues_only: + print( + "Filtering to include only text shapes with issues (overflow/overlap)" + ) + 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) + + print(f"Output saved to: {args.output}") + + # Report statistics + total_slides = len(inventory) + total_shapes = sum(len(shapes) for shapes in inventory.values()) + if args.issues_only: + if total_shapes > 0: + print( + f"Found {total_shapes} text elements with issues in {total_slides} slides" + ) + else: + print("No issues discovered") + else: + print( + f"Found text in {total_slides} slides with {total_shapes} text elements" + ) + + except Exception as e: + print(f"Error processing presentation: {e}") + import traceback + + traceback.print_exc() + sys.exit(1) + + +@dataclass +class ShapeWithPosition: + """A shape with its absolute position on the slide.""" + + shape: BaseShape + absolute_left: int # in EMUs + absolute_top: int # in EMUs + + +class ParagraphData: + """Data structure for paragraph properties extracted from a PowerPoint paragraph.""" + + def __init__(self, paragraph: Any): + """Initialize from a PowerPoint paragraph object. + + Args: + paragraph: The PowerPoint paragraph object + """ + 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 + + # Check for bullet formatting + if ( + hasattr(paragraph, "_p") + and paragraph._p is not None + and paragraph._p.pPr is not None + ): + pPr = paragraph._p.pPr + ns = "{http://schemas.openxmlformats.org/drawingml/2006/main}" + if ( + pPr.find(f"{ns}buChar") is not None + or pPr.find(f"{ns}buAutoNum") is not None + ): + self.bullet = True + if hasattr(paragraph, "level"): + self.level = paragraph.level + + # Add alignment if not LEFT (default) + if hasattr(paragraph, "alignment") and paragraph.alignment is not None: + alignment_map = { + PP_ALIGN.CENTER: "CENTER", + PP_ALIGN.RIGHT: "RIGHT", + PP_ALIGN.JUSTIFY: "JUSTIFY", + } + if paragraph.alignment in alignment_map: + self.alignment = alignment_map[paragraph.alignment] + + # Add spacing properties if set + if hasattr(paragraph, "space_before") and paragraph.space_before: + self.space_before = paragraph.space_before.pt + if hasattr(paragraph, "space_after") and paragraph.space_after: + self.space_after = paragraph.space_after.pt + + # Extract font properties from first run + if paragraph.runs: + first_run = paragraph.runs[0] + if hasattr(first_run, "font"): + font = first_run.font + if font.name: + self.font_name = font.name + if font.size: + self.font_size = font.size.pt + if font.bold is not None: + self.bold = font.bold + if font.italic is not None: + self.italic = font.italic + if font.underline is not None: + self.underline = font.underline + + # Handle color - both RGB and theme colors + try: + # Try RGB color first + if font.color.rgb: + self.color = str(font.color.rgb) + except (AttributeError, TypeError): + # Fall back to theme color + try: + if font.color.theme_color: + self.theme_color = font.color.theme_color.name + except (AttributeError, TypeError): + pass + + # Add line spacing if set + if hasattr(paragraph, "line_spacing") and paragraph.line_spacing is not None: + if hasattr(paragraph.line_spacing, "pt"): + self.line_spacing = round(paragraph.line_spacing.pt, 2) + else: + # Multiplier - convert to points + font_size = self.font_size if self.font_size else 12.0 + self.line_spacing = round(paragraph.line_spacing * font_size, 2) + + def to_dict(self) -> ParagraphDict: + """Convert to dictionary for JSON serialization, excluding None values.""" + result: ParagraphDict = {"text": self.text} + + # Add optional fields only if they have values + if self.bullet: + result["bullet"] = self.bullet + if self.level is not None: + result["level"] = self.level + if self.alignment: + result["alignment"] = self.alignment + if self.space_before is not None: + result["space_before"] = self.space_before + if self.space_after is not None: + result["space_after"] = self.space_after + if self.font_name: + result["font_name"] = self.font_name + if self.font_size is not None: + result["font_size"] = self.font_size + if self.bold is not None: + result["bold"] = self.bold + if self.italic is not None: + result["italic"] = self.italic + if self.underline is not None: + result["underline"] = self.underline + if self.color: + result["color"] = self.color + if self.theme_color: + result["theme_color"] = self.theme_color + if self.line_spacing is not None: + result["line_spacing"] = self.line_spacing + + return result + + +class ShapeData: + """Data structure for shape properties extracted from a PowerPoint shape.""" + + @staticmethod + def emu_to_inches(emu: int) -> float: + """Convert EMUs (English Metric Units) to inches.""" + return emu / 914400.0 + + @staticmethod + def inches_to_pixels(inches: float, dpi: int = 96) -> int: + """Convert inches to pixels at given DPI.""" + return int(inches * dpi) + + @staticmethod + def get_font_path(font_name: str) -> Optional[str]: + """Get the font file path for a given font name. + + Args: + font_name: Name of the font (e.g., 'Arial', 'Calibri') + + Returns: + Path to the font file, or None if not found + """ + system = platform.system() + + # Common font file variations to try + font_variations = [ + font_name, + font_name.lower(), + font_name.replace(" ", ""), + font_name.replace(" ", "-"), + ] + + # Define font directories and extensions by platform + if system == "Darwin": # macOS + font_dirs = [ + "/System/Library/Fonts/", + "/Library/Fonts/", + "~/Library/Fonts/", + ] + extensions = [".ttf", ".otf", ".ttc", ".dfont"] + else: # Linux + font_dirs = [ + "/usr/share/fonts/truetype/", + "/usr/local/share/fonts/", + "~/.fonts/", + ] + extensions = [".ttf", ".otf"] + + # Try to find the font file + from pathlib import Path + + for font_dir in font_dirs: + font_dir_path = Path(font_dir).expanduser() + if not font_dir_path.exists(): + continue + + # First try exact matches + for variant in font_variations: + for ext in extensions: + font_path = font_dir_path / f"{variant}{ext}" + if font_path.exists(): + return str(font_path) + + # Then try fuzzy matching - find files containing the font name + try: + for file_path in font_dir_path.iterdir(): + if file_path.is_file(): + file_name_lower = file_path.name.lower() + font_name_lower = font_name.lower().replace(" ", "") + if font_name_lower in file_name_lower and any( + file_name_lower.endswith(ext) for ext in extensions + ): + return str(file_path) + except (OSError, PermissionError): + continue + + return None + + @staticmethod + def get_slide_dimensions(slide: Any) -> tuple[Optional[int], Optional[int]]: + """Get slide dimensions from slide object. + + Args: + slide: Slide object + + Returns: + Tuple of (width_emu, height_emu) or (None, None) if not found + """ + try: + prs = slide.part.package.presentation_part.presentation + return prs.slide_width, prs.slide_height + except (AttributeError, TypeError): + return None, None + + @staticmethod + def get_default_font_size(shape: BaseShape, slide_layout: Any) -> Optional[float]: + """Extract default font size from slide layout for a placeholder shape. + + Args: + shape: Placeholder shape + slide_layout: Slide layout containing the placeholder definition + + Returns: + Default font size in points, or None if not found + """ + try: + if not hasattr(shape, "placeholder_format"): + return None + + shape_type = shape.placeholder_format.type # type: ignore + for layout_placeholder in slide_layout.placeholders: + if layout_placeholder.placeholder_format.type == shape_type: + # Find first defRPr element with sz (size) attribute + for elem in layout_placeholder.element.iter(): + if "defRPr" in elem.tag and (sz := elem.get("sz")): + return float(sz) / 100.0 # Convert EMUs to points + break + except Exception: + pass + return None + + def __init__( + self, + shape: BaseShape, + absolute_left: Optional[int] = None, + absolute_top: Optional[int] = None, + slide: Optional[Any] = None, + ): + """Initialize from a PowerPoint shape object. + + Args: + shape: The PowerPoint shape object (should be pre-validated) + absolute_left: Absolute left position in EMUs (for shapes in groups) + absolute_top: Absolute top position in EMUs (for shapes in groups) + slide: Optional slide object to get dimensions and layout information + """ + self.shape = shape # Store reference to original shape + self.shape_id: str = "" # Will be set after sorting + + # Get slide dimensions from slide object + self.slide_width_emu, self.slide_height_emu = ( + self.get_slide_dimensions(slide) if slide else (None, None) + ) + + # Get placeholder type if applicable + self.placeholder_type: Optional[str] = None + self.default_font_size: Optional[float] = None + if hasattr(shape, "is_placeholder") and shape.is_placeholder: # type: ignore + if shape.placeholder_format and shape.placeholder_format.type: # type: ignore + self.placeholder_type = ( + str(shape.placeholder_format.type).split(".")[-1].split(" ")[0] # type: ignore + ) + + # Get default font size from layout + if slide and hasattr(slide, "slide_layout"): + self.default_font_size = self.get_default_font_size( + shape, slide.slide_layout + ) + + # Get position information + # Use absolute positions if provided (for shapes in groups), otherwise use shape's position + left_emu = ( + absolute_left + if absolute_left is not None + else (shape.left if hasattr(shape, "left") else 0) + ) + top_emu = ( + absolute_top + if absolute_top is not None + else (shape.top if hasattr(shape, "top") else 0) + ) + + self.left: float = round(self.emu_to_inches(left_emu), 2) # type: ignore + self.top: float = round(self.emu_to_inches(top_emu), 2) # type: ignore + self.width: float = round( + self.emu_to_inches(shape.width if hasattr(shape, "width") else 0), + 2, # type: ignore + ) + self.height: float = round( + self.emu_to_inches(shape.height if hasattr(shape, "height") else 0), + 2, # type: ignore + ) + + # Store EMU positions for overflow calculations + self.left_emu = left_emu + self.top_emu = top_emu + self.width_emu = shape.width if hasattr(shape, "width") else 0 + self.height_emu = shape.height if hasattr(shape, "height") else 0 + + # Calculate overflow status + 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 + ] = {} # Dict of shape_id -> overlap area in sq inches + self.warnings: List[str] = [] + self._estimate_frame_overflow() + self._calculate_slide_overflow() + self._detect_bullet_issues() + + @property + def paragraphs(self) -> List[ParagraphData]: + """Calculate paragraphs from the shape's text frame.""" + if not self.shape or not hasattr(self.shape, "text_frame"): + return [] + + paragraphs = [] + for paragraph in self.shape.text_frame.paragraphs: # type: ignore + if paragraph.text.strip(): + paragraphs.append(ParagraphData(paragraph)) + return paragraphs + + def _get_default_font_size(self) -> int: + """Get default font size from theme text styles or use conservative default.""" + try: + if not ( + hasattr(self.shape, "part") and hasattr(self.shape.part, "slide_layout") + ): + return 14 + + slide_master = self.shape.part.slide_layout.slide_master # type: ignore + if not hasattr(slide_master, "element"): + return 14 + + # Determine theme style based on placeholder type + style_name = "bodyStyle" # Default + if self.placeholder_type and "TITLE" in self.placeholder_type: + style_name = "titleStyle" + + # Find font size in theme styles + for child in slide_master.element.iter(): + tag = child.tag.split("}")[-1] if "}" in child.tag else child.tag + if tag == style_name: + for elem in child.iter(): + if "sz" in elem.attrib: + return int(elem.attrib["sz"]) // 100 + except Exception: + pass + + return 14 # Conservative default for body text + + def _get_usable_dimensions(self, text_frame) -> Tuple[int, int]: + """Get usable width and height in pixels after accounting for margins.""" + # Default PowerPoint margins in inches + margins = {"top": 0.05, "bottom": 0.05, "left": 0.1, "right": 0.1} + + # Override with actual margins if set + if hasattr(text_frame, "margin_top") and text_frame.margin_top: + margins["top"] = self.emu_to_inches(text_frame.margin_top) + if hasattr(text_frame, "margin_bottom") and text_frame.margin_bottom: + margins["bottom"] = self.emu_to_inches(text_frame.margin_bottom) + if hasattr(text_frame, "margin_left") and text_frame.margin_left: + margins["left"] = self.emu_to_inches(text_frame.margin_left) + if hasattr(text_frame, "margin_right") and text_frame.margin_right: + margins["right"] = self.emu_to_inches(text_frame.margin_right) + + # Calculate usable area + usable_width = self.width - margins["left"] - margins["right"] + usable_height = self.height - margins["top"] - margins["bottom"] + + # Convert to pixels + return ( + self.inches_to_pixels(usable_width), + self.inches_to_pixels(usable_height), + ) + + def _wrap_text_line(self, line: str, max_width_px: int, draw, font) -> List[str]: + """Wrap a single line of text to fit within max_width_px.""" + if not line: + return [""] + + # Use textlength for efficient width calculation + if draw.textlength(line, font=font) <= max_width_px: + return [line] + + # Need to wrap - split into words + wrapped = [] + words = line.split(" ") + current_line = "" + + for word in words: + test_line = current_line + (" " if current_line else "") + word + if draw.textlength(test_line, font=font) <= max_width_px: + current_line = test_line + else: + if current_line: + wrapped.append(current_line) + current_line = word + + if current_line: + wrapped.append(current_line) + + return wrapped + + def _estimate_frame_overflow(self) -> None: + """Estimate if text overflows the shape bounds using PIL text measurement.""" + if not self.shape or not hasattr(self.shape, "text_frame"): + return + + text_frame = self.shape.text_frame # type: ignore + if not text_frame or not text_frame.paragraphs: + return + + # Get usable dimensions after accounting for margins + usable_width_px, usable_height_px = self._get_usable_dimensions(text_frame) + if usable_width_px <= 0 or usable_height_px <= 0: + return + + # Set up PIL for text measurement + dummy_img = Image.new("RGB", (1, 1)) + draw = ImageDraw.Draw(dummy_img) + + # Get default font size from placeholder or use conservative estimate + default_font_size = self._get_default_font_size() + + # Calculate total height of all paragraphs + total_height_px = 0 + + for para_idx, paragraph in enumerate(text_frame.paragraphs): + if not paragraph.text.strip(): + continue + + para_data = ParagraphData(paragraph) + + # Load font for this paragraph + font_name = para_data.font_name or "Arial" + font_size = int(para_data.font_size or default_font_size) + + font = None + font_path = self.get_font_path(font_name) + if font_path: + try: + font = ImageFont.truetype(font_path, size=font_size) + except Exception: + font = ImageFont.load_default() + else: + font = ImageFont.load_default() + + # Wrap all lines in this paragraph + all_wrapped_lines = [] + for line in paragraph.text.split("\n"): + wrapped = self._wrap_text_line(line, usable_width_px, draw, font) + all_wrapped_lines.extend(wrapped) + + if all_wrapped_lines: + # Calculate line height + if para_data.line_spacing: + # Custom line spacing explicitly set + line_height_px = para_data.line_spacing * 96 / 72 + else: + # PowerPoint default single spacing (1.0x font size) + line_height_px = font_size * 96 / 72 + + # Add space_before (except first paragraph) + if para_idx > 0 and para_data.space_before: + total_height_px += para_data.space_before * 96 / 72 + + # Add paragraph text height + total_height_px += len(all_wrapped_lines) * line_height_px + + # Add space_after + if para_data.space_after: + total_height_px += para_data.space_after * 96 / 72 + + # Check for overflow (ignore negligible overflows <= 0.05") + if total_height_px > usable_height_px: + overflow_px = total_height_px - usable_height_px + overflow_inches = round(overflow_px / 96.0, 2) + if overflow_inches > 0.05: # Only report significant overflows + self.frame_overflow_bottom = overflow_inches + + def _calculate_slide_overflow(self) -> None: + """Calculate if shape overflows the slide boundaries.""" + if self.slide_width_emu is None or self.slide_height_emu is None: + return + + # Check right overflow (ignore negligible overflows <= 0.01") + right_edge_emu = self.left_emu + self.width_emu + if right_edge_emu > self.slide_width_emu: + overflow_emu = right_edge_emu - self.slide_width_emu + overflow_inches = round(self.emu_to_inches(overflow_emu), 2) + if overflow_inches > 0.01: # Only report significant overflows + self.slide_overflow_right = overflow_inches + + # Check bottom overflow (ignore negligible overflows <= 0.01") + bottom_edge_emu = self.top_emu + self.height_emu + if bottom_edge_emu > self.slide_height_emu: + overflow_emu = bottom_edge_emu - self.slide_height_emu + overflow_inches = round(self.emu_to_inches(overflow_emu), 2) + if overflow_inches > 0.01: # Only report significant overflows + self.slide_overflow_bottom = overflow_inches + + def _detect_bullet_issues(self) -> None: + """Detect bullet point formatting issues in paragraphs.""" + if not self.shape or not hasattr(self.shape, "text_frame"): + return + + text_frame = self.shape.text_frame # type: ignore + if not text_frame or not text_frame.paragraphs: + return + + # Common bullet symbols that indicate manual bullets + bullet_symbols = ["•", "●", "○"] + + for paragraph in text_frame.paragraphs: + text = paragraph.text.strip() + # Check for manual bullet symbols + if text and any(text.startswith(symbol + " ") for symbol in bullet_symbols): + self.warnings.append( + "manual_bullet_symbol: use proper bullet formatting" + ) + break + + @property + def has_any_issues(self) -> bool: + """Check if shape has any issues (overflow, overlap, or warnings).""" + return ( + self.frame_overflow_bottom is not None + or self.slide_overflow_right is not None + or self.slide_overflow_bottom is not None + or len(self.overlapping_shapes) > 0 + or len(self.warnings) > 0 + ) + + def to_dict(self) -> ShapeDict: + """Convert to dictionary for JSON serialization.""" + result: ShapeDict = { + "left": self.left, + "top": self.top, + "width": self.width, + "height": self.height, + } + + # Add optional fields if present + if self.placeholder_type: + result["placeholder_type"] = self.placeholder_type + + if self.default_font_size: + result["default_font_size"] = self.default_font_size + + # Add overflow information only if there is overflow + overflow_data = {} + + # Add frame overflow if present + if self.frame_overflow_bottom is not None: + overflow_data["frame"] = {"overflow_bottom": self.frame_overflow_bottom} + + # Add slide overflow if present + slide_overflow = {} + if self.slide_overflow_right is not None: + slide_overflow["overflow_right"] = self.slide_overflow_right + if self.slide_overflow_bottom is not None: + slide_overflow["overflow_bottom"] = self.slide_overflow_bottom + if slide_overflow: + overflow_data["slide"] = slide_overflow + + # Only add overflow field if there is overflow + if overflow_data: + result["overflow"] = overflow_data + + # Add overlap field if there are overlapping shapes + if self.overlapping_shapes: + result["overlap"] = {"overlapping_shapes": self.overlapping_shapes} + + # Add warnings field if there are warnings + if self.warnings: + result["warnings"] = self.warnings + + # Add paragraphs after placeholder_type + result["paragraphs"] = [para.to_dict() for para in self.paragraphs] + + return result + + +def is_valid_shape(shape: BaseShape) -> bool: + """Check if a shape contains meaningful text content.""" + # Must have a text frame with content + if not hasattr(shape, "text_frame") or not shape.text_frame: # type: ignore + return False + + text = shape.text_frame.text.strip() # type: ignore + if not text: + return False + + # Skip slide numbers and numeric footers + if hasattr(shape, "is_placeholder") and shape.is_placeholder: # type: ignore + if shape.placeholder_format and shape.placeholder_format.type: # type: ignore + placeholder_type = ( + str(shape.placeholder_format.type).split(".")[-1].split(" ")[0] # type: ignore + ) + if placeholder_type == "SLIDE_NUMBER": + return False + if placeholder_type == "FOOTER" and text.isdigit(): + return False + + return True + + +def collect_shapes_with_absolute_positions( + shape: BaseShape, parent_left: int = 0, parent_top: int = 0 +) -> List[ShapeWithPosition]: + """Recursively collect all shapes with valid text, calculating absolute positions. + + For shapes within groups, their positions are relative to the group. + This function calculates the absolute position on the slide by accumulating + parent group offsets. + + Args: + shape: The shape to process + parent_left: Accumulated left offset from parent groups (in EMUs) + parent_top: Accumulated top offset from parent groups (in EMUs) + + Returns: + List of ShapeWithPosition objects with absolute positions + """ + if hasattr(shape, "shapes"): # GroupShape + result = [] + # Get this group's position + group_left = shape.left if hasattr(shape, "left") else 0 + group_top = shape.top if hasattr(shape, "top") else 0 + + # Calculate absolute position for this group + abs_group_left = parent_left + group_left + abs_group_top = parent_top + group_top + + # Process children with accumulated offsets + for child in shape.shapes: # type: ignore + result.extend( + collect_shapes_with_absolute_positions( + child, abs_group_left, abs_group_top + ) + ) + return result + + # Regular shape - check if it has valid text + if is_valid_shape(shape): + # Calculate absolute position + shape_left = shape.left if hasattr(shape, "left") else 0 + shape_top = shape.top if hasattr(shape, "top") else 0 + + return [ + ShapeWithPosition( + shape=shape, + absolute_left=parent_left + shape_left, + absolute_top=parent_top + shape_top, + ) + ] + + return [] + + +def sort_shapes_by_position(shapes: List[ShapeData]) -> List[ShapeData]: + """Sort shapes by visual position (top-to-bottom, left-to-right). + + Shapes within 0.5 inches vertically are considered on the same row. + """ + if not shapes: + return shapes + + # Sort by top position first + shapes = sorted(shapes, key=lambda s: (s.top, s.left)) + + # Group shapes by row (within 0.5 inches vertically) + result = [] + row = [shapes[0]] + row_top = shapes[0].top + + for shape in shapes[1:]: + if abs(shape.top - row_top) <= 0.5: + row.append(shape) + else: + # Sort current row by left position and add to result + result.extend(sorted(row, key=lambda s: s.left)) + row = [shape] + row_top = shape.top + + # Don't forget the last row + result.extend(sorted(row, key=lambda s: s.left)) + return result + + +def calculate_overlap( + rect1: Tuple[float, float, float, float], + rect2: Tuple[float, float, float, float], + tolerance: float = 0.05, +) -> Tuple[bool, float]: + """Calculate if and how much two rectangles overlap. + + Args: + rect1: (left, top, width, height) of first rectangle in inches + rect2: (left, top, width, height) of second rectangle in inches + tolerance: Minimum overlap in inches to consider as overlapping (default: 0.05") + + Returns: + Tuple of (overlaps, overlap_area) where: + - overlaps: True if rectangles overlap by more than tolerance + - overlap_area: Area of overlap in square inches + """ + left1, top1, w1, h1 = rect1 + left2, top2, w2, h2 = rect2 + + # Calculate overlap dimensions + overlap_width = min(left1 + w1, left2 + w2) - max(left1, left2) + overlap_height = min(top1 + h1, top2 + h2) - max(top1, top2) + + # Check if there's meaningful overlap (more than tolerance) + if overlap_width > tolerance and overlap_height > tolerance: + # Calculate overlap area in square inches + overlap_area = overlap_width * overlap_height + return True, round(overlap_area, 2) + + return False, 0 + + +def detect_overlaps(shapes: List[ShapeData]) -> None: + """Detect overlapping shapes and update their overlapping_shapes dictionaries. + + This function requires each ShapeData to have its shape_id already set. + It modifies the shapes in-place, adding shape IDs with overlap areas in square inches. + + Args: + shapes: List of ShapeData objects with shape_id attributes set + """ + n = len(shapes) + + # Compare each pair of shapes + for i in range(n): + for j in range(i + 1, n): + shape1 = shapes[i] + shape2 = shapes[j] + + # Ensure shape IDs are set + assert shape1.shape_id, f"Shape at index {i} has no shape_id" + assert shape2.shape_id, f"Shape at index {j} has no shape_id" + + rect1 = (shape1.left, shape1.top, shape1.width, shape1.height) + rect2 = (shape2.left, shape2.top, shape2.width, shape2.height) + + overlaps, overlap_area = calculate_overlap(rect1, rect2) + + if overlaps: + # Add shape IDs with overlap area in square inches + shape1.overlapping_shapes[shape2.shape_id] = overlap_area + shape2.overlapping_shapes[shape1.shape_id] = overlap_area + + +def extract_text_inventory( + pptx_path: Path, prs: Optional[Any] = None, issues_only: bool = False +) -> InventoryData: + """Extract text content from all slides in a PowerPoint presentation. + + Args: + pptx_path: Path to the PowerPoint file + prs: Optional Presentation object to use. If not provided, will load from pptx_path. + issues_only: If True, only include shapes that have overflow or overlap issues + + Returns a nested dictionary: {slide-N: {shape-N: ShapeData}} + Shapes are sorted by visual position (top-to-bottom, left-to-right). + The ShapeData objects contain the full shape information and can be + converted to dictionaries for JSON serialization using to_dict(). + """ + if prs is None: + prs = Presentation(str(pptx_path)) + inventory: InventoryData = {} + + for slide_idx, slide in enumerate(prs.slides): + # Collect all valid shapes from this slide with absolute positions + shapes_with_positions = [] + for shape in slide.shapes: # type: ignore + shapes_with_positions.extend(collect_shapes_with_absolute_positions(shape)) + + if not shapes_with_positions: + continue + + # Convert to ShapeData with absolute positions and slide reference + shape_data_list = [ + ShapeData( + swp.shape, + swp.absolute_left, + swp.absolute_top, + slide, + ) + for swp in shapes_with_positions + ] + + # Sort by visual position and assign stable IDs in one step + sorted_shapes = sort_shapes_by_position(shape_data_list) + for idx, shape_data in enumerate(sorted_shapes): + shape_data.shape_id = f"shape-{idx}" + + # Detect overlaps using the stable shape IDs + if len(sorted_shapes) > 1: + detect_overlaps(sorted_shapes) + + # Filter for issues only if requested (after overlap detection) + if issues_only: + sorted_shapes = [sd for sd in sorted_shapes if sd.has_any_issues] + + if not sorted_shapes: + continue + + # Create slide inventory using the stable shape IDs + inventory[f"slide-{slide_idx}"] = { + shape_data.shape_id: shape_data for shape_data in sorted_shapes + } + + return inventory + + +def get_inventory_as_dict(pptx_path: Path, issues_only: bool = False) -> InventoryDict: + """Extract text inventory and return as JSON-serializable dictionaries. + + This is a convenience wrapper around extract_text_inventory that returns + dictionaries instead of ShapeData objects, useful for testing and direct + JSON serialization. + + Args: + pptx_path: Path to the PowerPoint file + issues_only: If True, only include shapes that have overflow or overlap issues + + Returns: + Nested dictionary with all data serialized for JSON + """ + inventory = extract_text_inventory(pptx_path, issues_only=issues_only) + + # Convert ShapeData objects to dictionaries + dict_inventory: InventoryDict = {} + for slide_key, shapes in inventory.items(): + dict_inventory[slide_key] = { + shape_key: shape_data.to_dict() for shape_key, shape_data in shapes.items() + } + + return dict_inventory + + +def save_inventory(inventory: InventoryData, output_path: Path) -> None: + """Save inventory to JSON file with proper formatting. + + Converts ShapeData objects to dictionaries for JSON serialization. + """ + # Convert ShapeData objects to dictionaries + json_inventory: InventoryDict = {} + for slide_key, shapes in inventory.items(): + json_inventory[slide_key] = { + shape_key: shape_data.to_dict() for shape_key, shape_data in shapes.items() + } + + with open(output_path, "w", encoding="utf-8") as f: + json.dump(json_inventory, f, indent=2, ensure_ascii=False) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/pptx/scripts/office/helpers/__init__.py b/account/admin/skills/pptx/scripts/office/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account/admin/skills/pptx/scripts/office/helpers/merge_runs.py b/account/admin/skills/pptx/scripts/office/helpers/merge_runs.py new file mode 100644 index 0000000..ad7c25e --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/helpers/merge_runs.py @@ -0,0 +1,199 @@ +"""Merge adjacent runs with identical formatting in DOCX. + +Merges adjacent elements that have identical properties. +Works on runs in paragraphs and inside tracked changes (, ). + +Also: +- Removes rsid attributes from runs (revision metadata that doesn't affect rendering) +- Removes proofErr elements (spell/grammar markers that block merging) +""" + +from pathlib import Path + +import defusedxml.minidom + + +def merge_runs(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + _remove_elements(root, "proofErr") + _strip_run_rsid_attrs(root) + + containers = {run.parentNode for run in _find_elements(root, "r")} + + merge_count = 0 + for container in containers: + merge_count += _merge_runs_in(container) + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Merged {merge_count} runs" + + except Exception as e: + return 0, f"Error: {e}" + + + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def _get_child(parent, tag: str): + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + return child + return None + + +def _get_children(parent, tag: str) -> list: + results = [] + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(child) + return results + + +def _is_adjacent(elem1, elem2) -> bool: + node = elem1.nextSibling + while node: + if node == elem2: + return True + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + return False + + + + +def _remove_elements(root, tag: str): + for elem in _find_elements(root, tag): + if elem.parentNode: + elem.parentNode.removeChild(elem) + + +def _strip_run_rsid_attrs(root): + for run in _find_elements(root, "r"): + for attr in list(run.attributes.values()): + if "rsid" in attr.name.lower(): + run.removeAttribute(attr.name) + + + + +def _merge_runs_in(container) -> int: + merge_count = 0 + run = _first_child_run(container) + + while run: + while True: + next_elem = _next_element_sibling(run) + if next_elem and _is_run(next_elem) and _can_merge(run, next_elem): + _merge_run_content(run, next_elem) + container.removeChild(next_elem) + merge_count += 1 + else: + break + + _consolidate_text(run) + run = _next_sibling_run(run) + + return merge_count + + +def _first_child_run(container): + for child in container.childNodes: + if child.nodeType == child.ELEMENT_NODE and _is_run(child): + return child + return None + + +def _next_element_sibling(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + return sibling + sibling = sibling.nextSibling + return None + + +def _next_sibling_run(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + if _is_run(sibling): + return sibling + sibling = sibling.nextSibling + return None + + +def _is_run(node) -> bool: + name = node.localName or node.tagName + return name == "r" or name.endswith(":r") + + +def _can_merge(run1, run2) -> bool: + rpr1 = _get_child(run1, "rPr") + rpr2 = _get_child(run2, "rPr") + + if (rpr1 is None) != (rpr2 is None): + return False + if rpr1 is None: + return True + return rpr1.toxml() == rpr2.toxml() + + +def _merge_run_content(target, source): + for child in list(source.childNodes): + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name != "rPr" and not name.endswith(":rPr"): + target.appendChild(child) + + +def _consolidate_text(run): + t_elements = _get_children(run, "t") + + for i in range(len(t_elements) - 1, 0, -1): + curr, prev = t_elements[i], t_elements[i - 1] + + if _is_adjacent(prev, curr): + prev_text = prev.firstChild.data if prev.firstChild else "" + curr_text = curr.firstChild.data if curr.firstChild else "" + merged = prev_text + curr_text + + if prev.firstChild: + prev.firstChild.data = merged + else: + prev.appendChild(run.ownerDocument.createTextNode(merged)) + + if merged.startswith(" ") or merged.endswith(" "): + prev.setAttribute("xml:space", "preserve") + elif prev.hasAttribute("xml:space"): + prev.removeAttribute("xml:space") + + run.removeChild(curr) diff --git a/account/admin/skills/pptx/scripts/office/helpers/simplify_redlines.py b/account/admin/skills/pptx/scripts/office/helpers/simplify_redlines.py new file mode 100644 index 0000000..db963bb --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/helpers/simplify_redlines.py @@ -0,0 +1,197 @@ +"""Simplify tracked changes by merging adjacent w:ins or w:del elements. + +Merges adjacent elements from the same author into a single element. +Same for elements. This makes heavily-redlined documents easier to +work with by reducing the number of tracked change wrappers. + +Rules: +- Only merges w:ins with w:ins, w:del with w:del (same element type) +- Only merges if same author (ignores timestamp differences) +- Only merges if truly adjacent (only whitespace between them) +""" + +import xml.etree.ElementTree as ET +import zipfile +from pathlib import Path + +import defusedxml.minidom + +WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + + +def simplify_redlines(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + merge_count = 0 + + containers = _find_elements(root, "p") + _find_elements(root, "tc") + + for container in containers: + merge_count += _merge_tracked_changes_in(container, "ins") + merge_count += _merge_tracked_changes_in(container, "del") + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Simplified {merge_count} tracked changes" + + except Exception as e: + return 0, f"Error: {e}" + + +def _merge_tracked_changes_in(container, tag: str) -> int: + merge_count = 0 + + tracked = [ + child + for child in container.childNodes + if child.nodeType == child.ELEMENT_NODE and _is_element(child, tag) + ] + + if len(tracked) < 2: + return 0 + + i = 0 + while i < len(tracked) - 1: + curr = tracked[i] + next_elem = tracked[i + 1] + + if _can_merge_tracked(curr, next_elem): + _merge_tracked_content(curr, next_elem) + container.removeChild(next_elem) + tracked.pop(i + 1) + merge_count += 1 + else: + i += 1 + + return merge_count + + +def _is_element(node, tag: str) -> bool: + name = node.localName or node.tagName + return name == tag or name.endswith(f":{tag}") + + +def _get_author(elem) -> str: + author = elem.getAttribute("w:author") + if not author: + for attr in elem.attributes.values(): + if attr.localName == "author" or attr.name.endswith(":author"): + return attr.value + return author + + +def _can_merge_tracked(elem1, elem2) -> bool: + if _get_author(elem1) != _get_author(elem2): + return False + + node = elem1.nextSibling + while node and node != elem2: + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + + return True + + +def _merge_tracked_content(target, source): + while source.firstChild: + child = source.firstChild + source.removeChild(child) + target.appendChild(child) + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]: + if not doc_xml_path.exists(): + return {} + + try: + tree = ET.parse(doc_xml_path) + root = tree.getroot() + except ET.ParseError: + return {} + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + + return authors + + +def _get_authors_from_docx(docx_path: Path) -> dict[str, int]: + try: + with zipfile.ZipFile(docx_path, "r") as zf: + if "word/document.xml" not in zf.namelist(): + return {} + with zf.open("word/document.xml") as f: + tree = ET.parse(f) + root = tree.getroot() + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + return authors + except (zipfile.BadZipFile, ET.ParseError): + return {} + + +def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str: + modified_xml = modified_dir / "word" / "document.xml" + modified_authors = get_tracked_change_authors(modified_xml) + + if not modified_authors: + return default + + original_authors = _get_authors_from_docx(original_docx) + + new_changes: dict[str, int] = {} + for author, count in modified_authors.items(): + original_count = original_authors.get(author, 0) + diff = count - original_count + if diff > 0: + new_changes[author] = diff + + if not new_changes: + return default + + if len(new_changes) == 1: + return next(iter(new_changes)) + + raise ValueError( + f"Multiple authors added new changes: {new_changes}. " + "Cannot infer which author to validate." + ) diff --git a/account/admin/skills/pptx/scripts/office/pack.py b/account/admin/skills/pptx/scripts/office/pack.py new file mode 100644 index 0000000..db29ed8 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/pack.py @@ -0,0 +1,159 @@ +"""Pack a directory into a DOCX, PPTX, or XLSX file. + +Validates with auto-repair, condenses XML formatting, and creates the Office file. + +Usage: + python pack.py [--original ] [--validate true|false] + +Examples: + python pack.py unpacked/ output.docx --original input.docx + python pack.py unpacked/ output.pptx --validate false +""" + +import argparse +import sys +import shutil +import tempfile +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + +def pack( + input_directory: str, + output_file: str, + original_file: str | None = None, + validate: bool = True, + infer_author_func=None, +) -> tuple[None, str]: + input_dir = Path(input_directory) + output_path = Path(output_file) + suffix = output_path.suffix.lower() + + if not input_dir.is_dir(): + return None, f"Error: {input_dir} is not a directory" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file" + + if validate and original_file: + original_path = Path(original_file) + if original_path.exists(): + success, output = _run_validation( + input_dir, original_path, suffix, infer_author_func + ) + if output: + print(output) + if not success: + return None, f"Error: Validation failed for {input_dir}" + + with tempfile.TemporaryDirectory() as temp_dir: + temp_content_dir = Path(temp_dir) / "content" + shutil.copytree(input_dir, temp_content_dir) + + for pattern in ["*.xml", "*.rels"]: + for xml_file in temp_content_dir.rglob(pattern): + _condense_xml(xml_file) + + output_path.parent.mkdir(parents=True, exist_ok=True) + with zipfile.ZipFile(output_path, "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)) + + return None, f"Successfully packed {input_dir} to {output_file}" + + +def _run_validation( + unpacked_dir: Path, + original_file: Path, + suffix: str, + infer_author_func=None, +) -> tuple[bool, str | None]: + output_lines = [] + validators = [] + + if suffix == ".docx": + author = "Claude" + if infer_author_func: + try: + author = infer_author_func(unpacked_dir, original_file) + except ValueError as e: + print(f"Warning: {e} Using default author 'Claude'.", file=sys.stderr) + + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file), + RedliningValidator(unpacked_dir, original_file, author=author), + ] + elif suffix == ".pptx": + validators = [PPTXSchemaValidator(unpacked_dir, original_file)] + + if not validators: + return True, None + + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + output_lines.append(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + output_lines.append("All validations PASSED!") + + return success, "\n".join(output_lines) if output_lines else None + + +def _condense_xml(xml_file: Path) -> None: + try: + with open(xml_file, encoding="utf-8") as f: + dom = defusedxml.minidom.parse(f) + + for element in dom.getElementsByTagName("*"): + if element.tagName.endswith(":t"): + continue + + 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) + + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + except Exception as e: + print(f"ERROR: Failed to parse {xml_file.name}: {e}", file=sys.stderr) + raise + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Pack a directory into a DOCX, PPTX, or XLSX 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( + "--original", + help="Original file for validation comparison", + ) + parser.add_argument( + "--validate", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Run validation with auto-repair (default: true)", + ) + args = parser.parse_args() + + _, message = pack( + args.input_directory, + args.output_file, + original_file=args.original, + validate=args.validate, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd new file mode 100644 index 0000000..6454ef9 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd @@ -0,0 +1,1499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd new file mode 100644 index 0000000..afa4f46 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd new file mode 100644 index 0000000..64e66b8 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd @@ -0,0 +1,1085 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd new file mode 100644 index 0000000..687eea8 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd @@ -0,0 +1,11 @@ + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd new file mode 100644 index 0000000..6ac81b0 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd @@ -0,0 +1,3081 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd new file mode 100644 index 0000000..1dbf051 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..f1af17d --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..0a185ab --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd new file mode 100644 index 0000000..14ef488 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd @@ -0,0 +1,1676 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd new file mode 100644 index 0000000..c20f3bf --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd new file mode 100644 index 0000000..ac60252 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd new file mode 100644 index 0000000..424b8ba --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd new file mode 100644 index 0000000..2bddce2 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd new file mode 100644 index 0000000..8a8c18b --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd new file mode 100644 index 0000000..5c42706 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd new file mode 100644 index 0000000..853c341 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd new file mode 100644 index 0000000..da835ee --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd new file mode 100644 index 0000000..87ad265 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd new file mode 100644 index 0000000..9e86f1b --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd new file mode 100644 index 0000000..d0be42e --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd @@ -0,0 +1,4439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd new file mode 100644 index 0000000..8821dd1 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd @@ -0,0 +1,570 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd new file mode 100644 index 0000000..ca2575c --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd new file mode 100644 index 0000000..dd079e6 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..3dd6cf6 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..f1041e3 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd new file mode 100644 index 0000000..9c5b7a6 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd @@ -0,0 +1,3646 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd new file mode 100644 index 0000000..0f13678 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd @@ -0,0 +1,116 @@ + + + + + + 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 + + + + + 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: + <schema . . .> + . . . + <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. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + 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. + + + + + + In due course, we should install the relevant ISO 2- and 3-letter + codes as the enumerated possible values . . . + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd new file mode 100644 index 0000000..a6de9d2 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd new file mode 100644 index 0000000..10e978b --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd new file mode 100644 index 0000000..4248bf7 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd new file mode 100644 index 0000000..5649746 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/mce/mc.xsd b/account/admin/skills/pptx/scripts/office/schemas/mce/mc.xsd new file mode 100644 index 0000000..ef72545 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/mce/mc.xsd @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd new file mode 100644 index 0000000..f65f777 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd @@ -0,0 +1,560 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd new file mode 100644 index 0000000..6b00755 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd new file mode 100644 index 0000000..f321d33 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd new file mode 100644 index 0000000..364c6a9 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd new file mode 100644 index 0000000..fed9d15 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd new file mode 100644 index 0000000..680cf15 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd @@ -0,0 +1,4 @@ + + + + diff --git a/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd new file mode 100644 index 0000000..89ada90 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/account/admin/skills/pptx/scripts/office/soffice.py b/account/admin/skills/pptx/scripts/office/soffice.py new file mode 100644 index 0000000..c7f7e32 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/soffice.py @@ -0,0 +1,183 @@ +""" +Helper for running LibreOffice (soffice) in environments where AF_UNIX +sockets may be blocked (e.g., sandboxed VMs). Detects the restriction +at runtime and applies an LD_PRELOAD shim if needed. + +Usage: + from office.soffice import run_soffice, get_soffice_env + + # Option 1 – run soffice directly + result = run_soffice(["--headless", "--convert-to", "pdf", "input.docx"]) + + # Option 2 – get env dict for your own subprocess calls + env = get_soffice_env() + subprocess.run(["soffice", ...], env=env) +""" + +import os +import socket +import subprocess +import tempfile +from pathlib import Path + + +def get_soffice_env() -> dict: + env = os.environ.copy() + env["SAL_USE_VCLPLUGIN"] = "svp" + + if _needs_shim(): + shim = _ensure_shim() + env["LD_PRELOAD"] = str(shim) + + return env + + +def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess: + env = get_soffice_env() + return subprocess.run(["soffice"] + args, env=env, **kwargs) + + + +_SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" + + +def _needs_shim() -> bool: + try: + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.close() + return False + except OSError: + return True + + +def _ensure_shim() -> Path: + if _SHIM_SO.exists(): + return _SHIM_SO + + src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" + src.write_text(_SHIM_SOURCE) + subprocess.run( + ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], + check=True, + capture_output=True, + ) + src.unlink() + return _SHIM_SO + + + +_SHIM_SOURCE = r""" +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +static int (*real_socket)(int, int, int); +static int (*real_socketpair)(int, int, int, int[2]); +static int (*real_listen)(int, int); +static int (*real_accept)(int, struct sockaddr *, socklen_t *); +static int (*real_close)(int); +static int (*real_read)(int, void *, size_t); + +/* Per-FD bookkeeping (FDs >= 1024 are passed through unshimmed). */ +static int is_shimmed[1024]; +static int peer_of[1024]; +static int wake_r[1024]; /* accept() blocks reading this */ +static int wake_w[1024]; /* close() writes to this */ +static int listener_fd = -1; /* FD that received listen() */ + +__attribute__((constructor)) +static void init(void) { + real_socket = dlsym(RTLD_NEXT, "socket"); + real_socketpair = dlsym(RTLD_NEXT, "socketpair"); + real_listen = dlsym(RTLD_NEXT, "listen"); + real_accept = dlsym(RTLD_NEXT, "accept"); + real_close = dlsym(RTLD_NEXT, "close"); + real_read = dlsym(RTLD_NEXT, "read"); + for (int i = 0; i < 1024; i++) { + peer_of[i] = -1; + wake_r[i] = -1; + wake_w[i] = -1; + } +} + +/* ---- socket ---------------------------------------------------------- */ +int socket(int domain, int type, int protocol) { + if (domain == AF_UNIX) { + int fd = real_socket(domain, type, protocol); + if (fd >= 0) return fd; + /* socket(AF_UNIX) blocked – fall back to socketpair(). */ + int sv[2]; + if (real_socketpair(domain, type, protocol, sv) == 0) { + if (sv[0] >= 0 && sv[0] < 1024) { + is_shimmed[sv[0]] = 1; + peer_of[sv[0]] = sv[1]; + int wp[2]; + if (pipe(wp) == 0) { + wake_r[sv[0]] = wp[0]; + wake_w[sv[0]] = wp[1]; + } + } + return sv[0]; + } + errno = EPERM; + return -1; + } + return real_socket(domain, type, protocol); +} + +/* ---- listen ---------------------------------------------------------- */ +int listen(int sockfd, int backlog) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + listener_fd = sockfd; + return 0; + } + return real_listen(sockfd, backlog); +} + +/* ---- accept ---------------------------------------------------------- */ +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + /* Block until close() writes to the wake pipe. */ + if (wake_r[sockfd] >= 0) { + char buf; + real_read(wake_r[sockfd], &buf, 1); + } + errno = ECONNABORTED; + return -1; + } + return real_accept(sockfd, addr, addrlen); +} + +/* ---- close ----------------------------------------------------------- */ +int close(int fd) { + if (fd >= 0 && fd < 1024 && is_shimmed[fd]) { + int was_listener = (fd == listener_fd); + is_shimmed[fd] = 0; + + if (wake_w[fd] >= 0) { /* unblock accept() */ + char c = 0; + write(wake_w[fd], &c, 1); + real_close(wake_w[fd]); + wake_w[fd] = -1; + } + if (wake_r[fd] >= 0) { real_close(wake_r[fd]); wake_r[fd] = -1; } + if (peer_of[fd] >= 0) { real_close(peer_of[fd]); peer_of[fd] = -1; } + + if (was_listener) + _exit(0); /* conversion done – exit */ + } + return real_close(fd); +} +""" + + + +if __name__ == "__main__": + import sys + result = run_soffice(sys.argv[1:]) + sys.exit(result.returncode) diff --git a/account/admin/skills/pptx/scripts/office/unpack.py b/account/admin/skills/pptx/scripts/office/unpack.py new file mode 100644 index 0000000..0015253 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/unpack.py @@ -0,0 +1,132 @@ +"""Unpack Office files (DOCX, PPTX, XLSX) for editing. + +Extracts the ZIP archive, pretty-prints XML files, and optionally: +- Merges adjacent runs with identical formatting (DOCX only) +- Simplifies adjacent tracked changes from same author (DOCX only) + +Usage: + python unpack.py [options] + +Examples: + python unpack.py document.docx unpacked/ + python unpack.py presentation.pptx unpacked/ + python unpack.py document.docx unpacked/ --merge-runs false +""" + +import argparse +import sys +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from helpers.merge_runs import merge_runs as do_merge_runs +from helpers.simplify_redlines import simplify_redlines as do_simplify_redlines + +SMART_QUOTE_REPLACEMENTS = { + "\u201c": "“", + "\u201d": "”", + "\u2018": "‘", + "\u2019": "’", +} + + +def unpack( + input_file: str, + output_directory: str, + merge_runs: bool = True, + simplify_redlines: bool = True, +) -> tuple[None, str]: + input_path = Path(input_file) + output_path = Path(output_directory) + suffix = input_path.suffix.lower() + + if not input_path.exists(): + return None, f"Error: {input_file} does not exist" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {input_file} must be a .docx, .pptx, or .xlsx file" + + try: + output_path.mkdir(parents=True, exist_ok=True) + + with zipfile.ZipFile(input_path, "r") as zf: + zf.extractall(output_path) + + xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) + for xml_file in xml_files: + _pretty_print_xml(xml_file) + + message = f"Unpacked {input_file} ({len(xml_files)} XML files)" + + if suffix == ".docx": + if simplify_redlines: + simplify_count, _ = do_simplify_redlines(str(output_path)) + message += f", simplified {simplify_count} tracked changes" + + if merge_runs: + merge_count, _ = do_merge_runs(str(output_path)) + message += f", merged {merge_count} runs" + + for xml_file in xml_files: + _escape_smart_quotes(xml_file) + + return None, message + + except zipfile.BadZipFile: + return None, f"Error: {input_file} is not a valid Office file" + except Exception as e: + return None, f"Error unpacking: {e}" + + +def _pretty_print_xml(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="utf-8")) + except Exception: + pass + + +def _escape_smart_quotes(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + for char, entity in SMART_QUOTE_REPLACEMENTS.items(): + content = content.replace(char, entity) + xml_file.write_text(content, encoding="utf-8") + except Exception: + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Unpack an Office file (DOCX, PPTX, XLSX) for editing" + ) + parser.add_argument("input_file", help="Office file to unpack") + parser.add_argument("output_directory", help="Output directory") + parser.add_argument( + "--merge-runs", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent runs with identical formatting (DOCX only, default: true)", + ) + parser.add_argument( + "--simplify-redlines", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent tracked changes from same author (DOCX only, default: true)", + ) + args = parser.parse_args() + + _, message = unpack( + args.input_file, + args.output_directory, + merge_runs=args.merge_runs, + simplify_redlines=args.simplify_redlines, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/account/admin/skills/pptx/scripts/office/validate.py b/account/admin/skills/pptx/scripts/office/validate.py new file mode 100644 index 0000000..03b01f6 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validate.py @@ -0,0 +1,111 @@ +""" +Command line tool to validate Office document XML files against XSD schemas and tracked changes. + +Usage: + python validate.py [--original ] [--auto-repair] [--author NAME] + +The first argument can be either: +- An unpacked directory containing the Office document XML files +- A packed Office file (.docx/.pptx/.xlsx) which will be unpacked to a temp directory + +Auto-repair fixes: +- paraId/durableId values that exceed OOXML limits +- Missing xml:space="preserve" on w:t elements with whitespace +""" + +import argparse +import sys +import tempfile +import zipfile +from pathlib import Path + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + + +def main(): + parser = argparse.ArgumentParser(description="Validate Office document XML files") + parser.add_argument( + "path", + help="Path to unpacked directory or packed Office file (.docx/.pptx/.xlsx)", + ) + parser.add_argument( + "--original", + required=False, + default=None, + help="Path to original file (.docx/.pptx/.xlsx). If omitted, all XSD errors are reported and redlining validation is skipped.", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Enable verbose output", + ) + parser.add_argument( + "--auto-repair", + action="store_true", + help="Automatically repair common issues (hex IDs, whitespace preservation)", + ) + parser.add_argument( + "--author", + default="Claude", + help="Author name for redlining validation (default: Claude)", + ) + args = parser.parse_args() + + path = Path(args.path) + assert path.exists(), f"Error: {path} does not exist" + + original_file = None + if args.original: + original_file = Path(args.original) + assert original_file.is_file(), f"Error: {original_file} is not a file" + assert original_file.suffix.lower() in [".docx", ".pptx", ".xlsx"], ( + f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" + ) + + file_extension = (original_file or path).suffix.lower() + assert file_extension in [".docx", ".pptx", ".xlsx"], ( + f"Error: Cannot determine file type from {path}. Use --original or provide a .docx/.pptx/.xlsx file." + ) + + if path.is_file() and path.suffix.lower() in [".docx", ".pptx", ".xlsx"]: + temp_dir = tempfile.mkdtemp() + with zipfile.ZipFile(path, "r") as zf: + zf.extractall(temp_dir) + unpacked_dir = Path(temp_dir) + else: + assert path.is_dir(), f"Error: {path} is not a directory or Office file" + unpacked_dir = path + + match file_extension: + case ".docx": + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + if original_file: + validators.append( + RedliningValidator(unpacked_dir, original_file, verbose=args.verbose, author=args.author) + ) + case ".pptx": + validators = [ + PPTXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + case _: + print(f"Error: Validation not supported for file type {file_extension}") + sys.exit(1) + + if args.auto_repair: + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + print(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + print("All validations PASSED!") + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/pptx/scripts/office/validators/__init__.py b/account/admin/skills/pptx/scripts/office/validators/__init__.py new file mode 100644 index 0000000..db092ec --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validators/__init__.py @@ -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", +] diff --git a/account/admin/skills/pptx/scripts/office/validators/base.py b/account/admin/skills/pptx/scripts/office/validators/base.py new file mode 100644 index 0000000..db4a06a --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validators/base.py @@ -0,0 +1,847 @@ +""" +Base validator with common validation logic for document files. +""" + +import re +from pathlib import Path + +import defusedxml.minidom +import lxml.etree + + +class BaseSchemaValidator: + + IGNORED_VALIDATION_ERRORS = [ + "hyphenationZone", + "purl.org/dc/terms", + ] + + UNIQUE_ID_REQUIREMENTS = { + "comment": ("id", "file"), + "commentrangestart": ("id", "file"), + "commentrangeend": ("id", "file"), + "bookmarkstart": ("id", "file"), + "bookmarkend": ("id", "file"), + "sldid": ("id", "file"), + "sldmasterid": ("id", "global"), + "sldlayoutid": ("id", "global"), + "cm": ("authorid", "file"), + "sheet": ("sheetid", "file"), + "definedname": ("id", "file"), + "cxnsp": ("id", "file"), + "sp": ("id", "file"), + "pic": ("id", "file"), + "grpsp": ("id", "file"), + } + + EXCLUDED_ID_CONTAINERS = { + "sectionlst", + } + + ELEMENT_RELATIONSHIP_TYPES = {} + + SCHEMA_MAPPINGS = { + "word": "ISO-IEC29500-4_2016/wml.xsd", + "ppt": "ISO-IEC29500-4_2016/pml.xsd", + "xl": "ISO-IEC29500-4_2016/sml.xsd", + "[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", + "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": "ISO-IEC29500-4_2016/dml-chart.xsd", + "theme": "ISO-IEC29500-4_2016/dml-main.xsd", + "drawing": "ISO-IEC29500-4_2016/dml-main.xsd", + } + + MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006" + XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" + + 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" + ) + + MAIN_CONTENT_FOLDERS = {"word", "ppt", "xl"} + + 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=None, verbose=False): + self.unpacked_dir = Path(unpacked_dir).resolve() + self.original_file = Path(original_file) if original_file else None + self.verbose = verbose + + self.schemas_dir = Path(__file__).parent.parent / "schemas" + + 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): + raise NotImplementedError("Subclasses must implement the validate method") + + def repair(self) -> int: + return self.repair_whitespace_preservation() + + def repair_whitespace_preservation(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if elem.tagName.endswith(":t") and elem.firstChild: + text = elem.firstChild.nodeValue + if text and (text.startswith((' ', '\t')) or text.endswith((' ', '\t'))): + if elem.getAttribute("xml:space") != "preserve": + elem.setAttribute("xml:space", "preserve") + text_preview = repr(text[:30]) + "..." if len(text) > 30 else repr(text) + print(f" Repaired: {xml_file.name}: Added xml:space='preserve' to {elem.tagName}: {text_preview}") + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + def validate_xml(self): + errors = [] + + for xml_file in self.xml_files: + try: + 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): + errors = [] + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + declared = set(root.nsmap.keys()) - {None} + + 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): + errors = [] + global_ids = {} + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + file_ids = {} + + mc_elements = root.xpath( + ".//mc:AlternateContent", namespaces={"mc": self.MC_NAMESPACE} + ) + for elem in mc_elements: + elem.getparent().remove(elem) + + for elem in root.iter(): + tag = ( + elem.tag.split("}")[-1].lower() + if "}" in elem.tag + else elem.tag.lower() + ) + + if tag in self.UNIQUE_ID_REQUIREMENTS: + in_excluded_container = any( + ancestor.tag.split("}")[-1].lower() in self.EXCLUDED_ID_CONTAINERS + for ancestor in elem.iterancestors() + ) + if in_excluded_container: + continue + + attr_name, scope = self.UNIQUE_ID_REQUIREMENTS[tag] + + 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": + 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": + 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): + errors = [] + + rels_files = list(self.unpacked_dir.rglob("*.rels")) + + if not rels_files: + if self.verbose: + print("PASSED - No .rels files found") + return True + + 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") + ): + all_files.append(file_path.resolve()) + + all_referenced_files = set() + + if self.verbose: + print( + f"Found {len(rels_files)} .rels files and {len(all_files)} target files" + ) + + for rels_file in rels_files: + try: + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + rels_dir = rels_file.parent + + 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:") + ): + if target.startswith("/"): + target_path = self.unpacked_dir / target.lstrip("/") + elif rels_file.name == ".rels": + target_path = self.unpacked_dir / target + else: + base_dir = rels_dir.parent + target_path = base_dir / target + + 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)) + + 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}") + + 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): + import lxml.etree + + errors = [] + + for xml_file in self.xml_files: + if xml_file.suffix == ".rels": + continue + + rels_dir = xml_file.parent / "_rels" + rels_file = rels_dir / f"{xml_file.name}.rels" + + if not rels_file.exists(): + continue + + try: + 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: + 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)" + ) + type_name = ( + rel_type.split("/")[-1] if "/" in rel_type else rel_type + ) + rid_to_type[rid] = type_name + + xml_root = lxml.etree.parse(str(xml_file)).getroot() + + r_ns = self.OFFICE_RELATIONSHIPS_NAMESPACE + rid_attrs_to_check = ["id", "embed", "link"] + for elem in xml_root.iter(): + for attr_name in rid_attrs_to_check: + rid_attr = elem.get(f"{{{r_ns}}}{attr_name}") + if not rid_attr: + continue + xml_rel_path = xml_file.relative_to(self.unpacked_dir) + elem_name = ( + elem.tag.split("}")[-1] if "}" in elem.tag else elem.tag + ) + + if rid_attr not in rid_to_type: + errors.append( + f" {xml_rel_path}: Line {elem.sourceline}: " + f"<{elem_name}> r:{attr_name} references non-existent relationship '{rid_attr}' " + f"(valid IDs: {', '.join(sorted(rid_to_type.keys())[:5])}{'...' if len(rid_to_type) > 5 else ''})" + ) + elif attr_name == "id" and self.ELEMENT_RELATIONSHIP_TYPES: + expected_type = self._get_expected_relationship_type( + elem_name + ) + if expected_type: + actual_type = rid_to_type[rid_attr] + 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): + elem_lower = element_name.lower() + + if elem_lower in self.ELEMENT_RELATIONSHIP_TYPES: + return self.ELEMENT_RELATIONSHIP_TYPES[elem_lower] + + if elem_lower.endswith("id") and len(elem_lower) > 2: + prefix = elem_lower[:-2] + if prefix.endswith("master"): + return prefix.lower() + elif prefix.endswith("layout"): + return prefix.lower() + else: + if prefix == "sld": + return "slide" + return prefix.lower() + + if elem_lower.endswith("reference") and len(elem_lower) > 9: + prefix = elem_lower[:-9] + return prefix.lower() + + return None + + def validate_content_types(self): + errors = [] + + 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: + root = lxml.etree.parse(str(content_types_file)).getroot() + declared_parts = set() + declared_extensions = set() + + 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("/")) + + 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()) + + declarable_roots = { + "sld", + "sldLayout", + "sldMaster", + "presentation", + "document", + "workbook", + "worksheet", + "theme", + } + + 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", + } + + all_files = list(self.unpacked_dir.rglob("*")) + all_files = [f for f in all_files if f.is_file()] + + for xml_file in self.xml_files: + path_str = str(xml_file.relative_to(self.unpacked_dir)).replace( + "\\", "/" + ) + + 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 + + for file_path in all_files: + 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: + 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: ' + ) + + 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): + xml_file = Path(xml_file).resolve() + unpacked_dir = self.unpacked_dir.resolve() + + is_valid, current_errors = self._validate_single_file_xsd( + xml_file, unpacked_dir + ) + + if is_valid is None: + return None, set() + elif is_valid: + return True, set() + + original_errors = self._get_original_file_errors(xml_file) + + assert current_errors is not None + new_errors = current_errors - original_errors + + new_errors = { + e for e in new_errors + if not any(pattern in e for pattern in self.IGNORED_VALIDATION_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: + if verbose: + print( + f"PASSED - No new errors (original had {len(current_errors)} errors)" + ) + return True, set() + + def validate_against_xsd(self): + 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: + original_error_count += 1 + valid_count += 1 + continue + + new_errors.append(f" {relative_path}: {len(new_file_errors)} new error(s)") + for error in list(new_file_errors)[:3]: + new_errors.append( + f" - {error[:250]}..." if len(error) > 250 else f" - {error}" + ) + + 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): + if xml_file.name in self.SCHEMA_MAPPINGS: + return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.name] + + if xml_file.suffix == ".rels": + return self.schemas_dir / self.SCHEMA_MAPPINGS[".rels"] + + if "charts/" in str(xml_file) and xml_file.name.startswith("chart"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["chart"] + + if "theme/" in str(xml_file) and xml_file.name.startswith("theme"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["theme"] + + 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): + xml_string = lxml.etree.tostring(xml_doc, encoding="unicode") + xml_copy = lxml.etree.fromstring(xml_string) + + for elem in xml_copy.iter(): + attrs_to_remove = [] + + for attr in elem.attrib: + if "{" in attr: + ns = attr.split("}")[0][1:] + if ns not in self.OOXML_NAMESPACES: + attrs_to_remove.append(attr) + + for attr in attrs_to_remove: + del elem.attrib[attr] + + self._remove_ignorable_elements(xml_copy) + + return lxml.etree.ElementTree(xml_copy) + + def _remove_ignorable_elements(self, root): + elements_to_remove = [] + + for elem in list(root): + 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 + + self._remove_ignorable_elements(elem) + + for elem in elements_to_remove: + root.remove(elem) + + def _preprocess_for_mc_ignorable(self, xml_doc): + root = xml_doc.getroot() + + 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): + schema_path = self._get_schema_path(xml_file) + if not schema_path: + return None, None + + try: + 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) + + 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) + + 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) + + if schema.validate(xml_doc): + return True, set() + else: + errors = set() + for error in schema.error_log: + errors.add(error.message) + return False, errors + + except Exception as e: + return False, {str(e)} + + def _get_original_file_errors(self, xml_file): + if self.original_file is None: + return set() + + import tempfile + import zipfile + + 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) + + with zipfile.ZipFile(self.original_file, "r") as zip_ref: + zip_ref.extractall(temp_path) + + original_xml_file = temp_path / relative_path + + if not original_xml_file.exists(): + return set() + + 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): + warnings = [] + template_pattern = re.compile(r"\{\{[^}]*\}\}") + + 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 + + for elem in xml_copy.iter(): + 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.") diff --git a/account/admin/skills/pptx/scripts/office/validators/docx.py b/account/admin/skills/pptx/scripts/office/validators/docx.py new file mode 100644 index 0000000..fec405e --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validators/docx.py @@ -0,0 +1,446 @@ +""" +Validator for Word document XML files against XSD schemas. +""" + +import random +import re +import tempfile +import zipfile + +import defusedxml.minidom +import lxml.etree + +from .base import BaseSchemaValidator + + +class DOCXSchemaValidator(BaseSchemaValidator): + + WORD_2006_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + W14_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml" + W16CID_NAMESPACE = "http://schemas.microsoft.com/office/word/2016/wordml/cid" + + ELEMENT_RELATIONSHIP_TYPES = {} + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_whitespace_preservation(): + all_valid = False + + if not self.validate_deletions(): + all_valid = False + + if not self.validate_insertions(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_id_constraints(): + all_valid = False + + if not self.validate_comment_markers(): + all_valid = False + + self.compare_paragraph_counts() + + return all_valid + + def validate_whitespace_preservation(self): + errors = [] + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + + for elem in root.iter(f"{{{self.WORD_2006_NAMESPACE}}}t"): + if elem.text: + text = elem.text + if re.search(r"^[ \t\n\r]", text) or re.search( + r"[ \t\n\r]$", text + ): + xml_space_attr = f"{{{self.XML_NAMESPACE}}}space" + if ( + xml_space_attr not in elem.attrib + or elem.attrib[xml_space_attr] != "preserve" + ): + 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): + 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} + + for t_elem in root.xpath(".//w:del//w:t", namespaces=namespaces): + if t_elem.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}: found within : {text_preview}" + ) + + for instr_elem in root.xpath( + ".//w:del//w:instrText", namespaces=namespaces + ): + text_preview = ( + repr(instr_elem.text or "")[:50] + "..." + if len(repr(instr_elem.text or "")) > 50 + else repr(instr_elem.text or "") + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {instr_elem.sourceline}: found within (use ): {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 = 0 + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + 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): + original = self.original_file + if original is None: + return 0 + + count = 0 + + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(original, "r") as zip_ref: + zip_ref.extractall(temp_dir) + + doc_xml_path = temp_dir + "/word/document.xml" + root = lxml.etree.parse(doc_xml_path).getroot() + + 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): + 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} + + 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}: within : {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): + 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})") + + def _parse_id_value(self, val: str, base: int = 16) -> int: + return int(val, base) + + def validate_id_constraints(self): + errors = [] + para_id_attr = f"{{{self.W14_NAMESPACE}}}paraId" + durable_id_attr = f"{{{self.W16CID_NAMESPACE}}}durableId" + + for xml_file in self.xml_files: + try: + for elem in lxml.etree.parse(str(xml_file)).iter(): + if val := elem.get(para_id_attr): + if self._parse_id_value(val, base=16) >= 0x80000000: + errors.append( + f" {xml_file.name}:{elem.sourceline}: paraId={val} >= 0x80000000" + ) + + if val := elem.get(durable_id_attr): + if xml_file.name == "numbering.xml": + try: + if self._parse_id_value(val, base=10) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except ValueError: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} must be decimal in numbering.xml" + ) + else: + if self._parse_id_value(val, base=16) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except Exception: + pass + + if errors: + print(f"FAILED - {len(errors)} ID constraint violations:") + for e in errors: + print(e) + elif self.verbose: + print("PASSED - All paraId/durableId values within constraints") + return not errors + + def validate_comment_markers(self): + errors = [] + + document_xml = None + comments_xml = None + for xml_file in self.xml_files: + if xml_file.name == "document.xml" and "word" in str(xml_file): + document_xml = xml_file + elif xml_file.name == "comments.xml": + comments_xml = xml_file + + if not document_xml: + if self.verbose: + print("PASSED - No document.xml found (skipping comment validation)") + return True + + try: + doc_root = lxml.etree.parse(str(document_xml)).getroot() + namespaces = {"w": self.WORD_2006_NAMESPACE} + + range_starts = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeStart", namespaces=namespaces + ) + } + range_ends = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeEnd", namespaces=namespaces + ) + } + references = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentReference", namespaces=namespaces + ) + } + + orphaned_ends = range_ends - range_starts + for comment_id in sorted( + orphaned_ends, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeEnd id="{comment_id}" has no matching commentRangeStart' + ) + + orphaned_starts = range_starts - range_ends + for comment_id in sorted( + orphaned_starts, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeStart id="{comment_id}" has no matching commentRangeEnd' + ) + + comment_ids = set() + if comments_xml and comments_xml.exists(): + comments_root = lxml.etree.parse(str(comments_xml)).getroot() + comment_ids = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in comments_root.xpath( + ".//w:comment", namespaces=namespaces + ) + } + + marker_ids = range_starts | range_ends | references + invalid_refs = marker_ids - comment_ids + for comment_id in sorted( + invalid_refs, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + if comment_id: + errors.append( + f' document.xml: marker id="{comment_id}" references non-existent comment' + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append(f" Error parsing XML: {e}") + + if errors: + print(f"FAILED - {len(errors)} comment marker violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All comment markers properly paired") + return True + + def repair(self) -> int: + repairs = super().repair() + repairs += self.repair_durableId() + return repairs + + def repair_durableId(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if not elem.hasAttribute("w16cid:durableId"): + continue + + durable_id = elem.getAttribute("w16cid:durableId") + needs_repair = False + + if xml_file.name == "numbering.xml": + try: + needs_repair = ( + self._parse_id_value(durable_id, base=10) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + else: + try: + needs_repair = ( + self._parse_id_value(durable_id, base=16) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + + if needs_repair: + value = random.randint(1, 0x7FFFFFFE) + if xml_file.name == "numbering.xml": + new_id = str(value) + else: + new_id = f"{value:08X}" + + elem.setAttribute("w16cid:durableId", new_id) + print( + f" Repaired: {xml_file.name}: durableId {durable_id} → {new_id}" + ) + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/account/admin/skills/pptx/scripts/office/validators/pptx.py b/account/admin/skills/pptx/scripts/office/validators/pptx.py new file mode 100644 index 0000000..09842aa --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validators/pptx.py @@ -0,0 +1,275 @@ +""" +Validator for PowerPoint presentation XML files against XSD schemas. +""" + +import re + +from .base import BaseSchemaValidator + + +class PPTXSchemaValidator(BaseSchemaValidator): + + PRESENTATIONML_NAMESPACE = ( + "http://schemas.openxmlformats.org/presentationml/2006/main" + ) + + ELEMENT_RELATIONSHIP_TYPES = { + "sldid": "slide", + "sldmasterid": "slidemaster", + "notesmasterid": "notesmaster", + "sldlayoutid": "slidelayout", + "themeid": "theme", + "tablestyleid": "tablestyles", + } + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_uuid_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_slide_layout_ids(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_notes_slide_references(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_no_duplicate_slide_layouts(): + all_valid = False + + return all_valid + + def validate_uuid_ids(self): + import lxml.etree + + errors = [] + 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() + + for elem in root.iter(): + for attr, value in elem.attrib.items(): + attr_name = attr.split("}")[-1].lower() + if attr_name == "id" or attr_name.endswith("id"): + if self._looks_like_uuid(value): + 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): + clean_value = value.strip("{}()").replace("-", "") + return len(clean_value) == 32 and all(c.isalnum() for c in clean_value) + + def validate_slide_layout_ids(self): + import lxml.etree + + errors = [] + + 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: + root = lxml.etree.parse(str(slide_master)).getroot() + + 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 + + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + 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")) + + 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): + import lxml.etree + + 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() + + 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): + import lxml.etree + + errors = [] + notes_slide_references = {} + + 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: + root = lxml.etree.parse(str(rels_file)).getroot() + + 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: + normalized_target = target.replace("../", "") + + slide_name = rels_file.stem.replace( + ".xml", "" + ) + + 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}" + ) + + 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.") diff --git a/account/admin/skills/pptx/scripts/office/validators/redlining.py b/account/admin/skills/pptx/scripts/office/validators/redlining.py new file mode 100644 index 0000000..71c81b6 --- /dev/null +++ b/account/admin/skills/pptx/scripts/office/validators/redlining.py @@ -0,0 +1,247 @@ +""" +Validator for tracked changes in Word documents. +""" + +import subprocess +import tempfile +import zipfile +from pathlib import Path + + +class RedliningValidator: + + def __init__(self, unpacked_dir, original_docx, verbose=False, author="Claude"): + self.unpacked_dir = Path(unpacked_dir) + self.original_docx = Path(original_docx) + self.verbose = verbose + self.author = author + self.namespaces = { + "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + } + + def repair(self) -> int: + return 0 + + def validate(self): + 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 + + try: + import xml.etree.ElementTree as ET + + tree = ET.parse(modified_file) + root = tree.getroot() + + del_elements = root.findall(".//w:del", self.namespaces) + ins_elements = root.findall(".//w:ins", self.namespaces) + + author_del_elements = [ + elem + for elem in del_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + author_ins_elements = [ + elem + for elem in ins_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + + if not author_del_elements and not author_ins_elements: + if self.verbose: + print(f"PASSED - No tracked changes by {self.author} found.") + return True + + except Exception: + pass + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + 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 + + 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 + + self._remove_author_tracked_changes(original_root) + self._remove_author_tracked_changes(modified_root) + + modified_text = self._extract_text_content(modified_root) + original_text = self._extract_text_content(original_root) + + if modified_text != original_text: + error_message = self._generate_detailed_diff( + original_text, modified_text + ) + print(error_message) + return False + + if self.verbose: + print(f"PASSED - All changes by {self.author} are properly tracked") + return True + + def _generate_detailed_diff(self, original_text, modified_text): + error_parts = [ + f"FAILED - Document text doesn't match after removing {self.author}'s tracked changes", + "", + "Likely causes:", + " 1. Modified text inside another author's or tags", + " 2. Made edits without proper tracked changes", + " 3. Didn't nest inside when deleting another's insertion", + "", + "For pre-redlined documents, use correct patterns:", + " - To reject another's INSERTION: Nest inside their ", + " - To restore another's DELETION: Add new AFTER their ", + "", + ] + + 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): + try: + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + 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") + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "--word-diff-regex=.", + "-U0", + "--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) + + if content_lines: + return "\n".join(content_lines) + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "-U0", + "--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): + pass + + return None + + def _remove_author_tracked_changes(self, root): + ins_tag = f"{{{self.namespaces['w']}}}ins" + del_tag = f"{{{self.namespaces['w']}}}del" + author_attr = f"{{{self.namespaces['w']}}}author" + + for parent in root.iter(): + to_remove = [] + for child in parent: + if child.tag == ins_tag and child.get(author_attr) == self.author: + to_remove.append(child) + for elem in to_remove: + parent.remove(elem) + + 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) == self.author: + to_process.append((child, list(parent).index(child))) + + for del_elem, del_index in reversed(to_process): + for elem in del_elem.iter(): + if elem.tag == deltext_tag: + elem.tag = t_tag + + for child in reversed(list(del_elem)): + parent.insert(del_index, child) + parent.remove(del_elem) + + def _extract_text_content(self, root): + p_tag = f"{{{self.namespaces['w']}}}p" + t_tag = f"{{{self.namespaces['w']}}}t" + + paragraphs = [] + for p_elem in root.findall(f".//{p_tag}"): + 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) + if paragraph_text: + paragraphs.append(paragraph_text) + + return "\n".join(paragraphs) + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/account/admin/skills/pptx/scripts/rearrange.py b/account/admin/skills/pptx/scripts/rearrange.py new file mode 100644 index 0000000..2519911 --- /dev/null +++ b/account/admin/skills/pptx/scripts/rearrange.py @@ -0,0 +1,231 @@ +#!/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 + +This will create output.pptx using slides from template.pptx in the specified order. +Slides can be repeated (e.g., 34 appears twice). +""" + +import argparse +import shutil +import sys +from copy import deepcopy +from pathlib import Path + +import six +from pptx import Presentation + + +def main(): + parser = argparse.ArgumentParser( + description="Rearrange PowerPoint slides based on a sequence of indices.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python rearrange.py template.pptx output.pptx 0,34,34,50,52 + Creates output.pptx using slides 0, 34 (twice), 50, and 52 from template.pptx + + python rearrange.py template.pptx output.pptx 5,3,1,2,4 + Creates output.pptx with slides reordered as specified + +Note: Slide indices are 0-based (first slide is 0, second is 1, etc.) + """, + ) + + parser.add_argument("template", help="Path to template PPTX file") + parser.add_argument("output", help="Path for output PPTX file") + parser.add_argument( + "sequence", help="Comma-separated sequence of slide indices (0-based)" + ) + + args = parser.parse_args() + + # Parse the slide sequence + try: + slide_sequence = [int(x.strip()) for x in args.sequence.split(",")] + except ValueError: + print( + "Error: Invalid sequence format. Use comma-separated integers (e.g., 0,34,34,50,52)" + ) + sys.exit(1) + + # Check template exists + template_path = Path(args.template) + if not template_path.exists(): + print(f"Error: Template file not found: {args.template}") + sys.exit(1) + + # Create output directory if needed + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + + try: + rearrange_presentation(template_path, output_path, slide_sequence) + except ValueError as e: + print(f"Error: {e}") + sys.exit(1) + except Exception as e: + print(f"Error processing presentation: {e}") + sys.exit(1) + + +def duplicate_slide(pres, index): + """Duplicate a slide in the presentation.""" + source = pres.slides[index] + + # Use source's layout to preserve formatting + new_slide = pres.slides.add_slide(source.slide_layout) + + # Collect all image and media relationships from the source slide + image_rels = {} + for rel_id, rel in six.iteritems(source.part.rels): + if "image" in rel.reltype or "media" in rel.reltype: + image_rels[rel_id] = rel + + # CRITICAL: Clear placeholder shapes to avoid duplicates + for shape in new_slide.shapes: + sp = shape.element + sp.getparent().remove(sp) + + # Copy all shapes from source + for shape in source.shapes: + el = shape.element + new_el = deepcopy(el) + new_slide.shapes._spTree.insert_element_before(new_el, "p:extLst") + + # Handle picture shapes - need to update the blip reference + # Look for all blip elements (they can be in pic or other contexts) + # Using the element's own xpath method without namespaces argument + blips = new_el.xpath(".//a:blip[@r:embed]") + for blip in blips: + old_rId = blip.get( + "{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed" + ) + if old_rId in image_rels: + # Create a new relationship in the destination slide for this image + old_rel = image_rels[old_rId] + # get_or_add returns the rId directly, or adds and returns new rId + new_rId = new_slide.part.rels.get_or_add( + old_rel.reltype, old_rel._target + ) + # Update the blip's embed reference to use the new relationship ID + blip.set( + "{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed", + new_rId, + ) + + # Copy any additional image/media relationships that might be referenced elsewhere + for rel_id, rel in image_rels.items(): + try: + new_slide.part.rels.get_or_add(rel.reltype, rel._target) + except Exception: + pass # Relationship might already exist + + return new_slide + + +def delete_slide(pres, index): + """Delete a slide from the presentation.""" + rId = pres.slides._sldIdLst[index].rId + pres.part.drop_rel(rId) + del pres.slides._sldIdLst[index] + + +def reorder_slides(pres, slide_index, target_index): + """Move a slide from one position to another.""" + slides = pres.slides._sldIdLst + + # Remove slide element from current position + slide_element = slides[slide_index] + slides.remove(slide_element) + + # Insert at target position + slides.insert(target_index, slide_element) + + +def rearrange_presentation(template_path, output_path, slide_sequence): + """ + Create a new presentation with slides from template in specified order. + + Args: + template_path: Path to template PPTX file + output_path: Path for output PPTX file + slide_sequence: List of slide indices (0-based) to include + """ + # Copy template to preserve dimensions and theme + if template_path != output_path: + shutil.copy2(template_path, output_path) + prs = Presentation(output_path) + else: + prs = Presentation(template_path) + + total_slides = len(prs.slides) + + # Validate indices + for idx in slide_sequence: + if idx < 0 or idx >= total_slides: + raise ValueError(f"Slide index {idx} out of range (0-{total_slides - 1})") + + # Track original slides and their duplicates + slide_map = [] # List of actual slide indices for final presentation + duplicated = {} # Track duplicates: original_idx -> [duplicate_indices] + + # Step 1: DUPLICATE repeated slides + print(f"Processing {len(slide_sequence)} slides from template...") + for i, template_idx in enumerate(slide_sequence): + if template_idx in duplicated and duplicated[template_idx]: + # Already duplicated this slide, use the duplicate + slide_map.append(duplicated[template_idx].pop(0)) + print(f" [{i}] Using duplicate of slide {template_idx}") + elif slide_sequence.count(template_idx) > 1 and template_idx not in duplicated: + # First occurrence of a repeated slide - create duplicates + slide_map.append(template_idx) + duplicates = [] + count = slide_sequence.count(template_idx) - 1 + print( + f" [{i}] Using original slide {template_idx}, creating {count} duplicate(s)" + ) + for _ in range(count): + duplicate_slide(prs, template_idx) + duplicates.append(len(prs.slides) - 1) + duplicated[template_idx] = duplicates + else: + # Unique slide or first occurrence already handled, use original + slide_map.append(template_idx) + print(f" [{i}] Using original slide {template_idx}") + + # Step 2: DELETE unwanted slides (work backwards) + slides_to_keep = set(slide_map) + print(f"\nDeleting {len(prs.slides) - len(slides_to_keep)} unused slides...") + for i in range(len(prs.slides) - 1, -1, -1): + if i not in slides_to_keep: + delete_slide(prs, i) + # Update slide_map indices after deletion + slide_map = [idx - 1 if idx > i else idx for idx in slide_map] + + # Step 3: REORDER to final sequence + print(f"Reordering {len(slide_map)} slides to final sequence...") + for target_pos in range(len(slide_map)): + # Find which slide should be at target_pos + current_pos = slide_map[target_pos] + if current_pos != target_pos: + reorder_slides(prs, current_pos, target_pos) + # Update slide_map: the move shifts other slides + for i in range(len(slide_map)): + if slide_map[i] > current_pos and slide_map[i] <= target_pos: + slide_map[i] -= 1 + elif slide_map[i] < current_pos and slide_map[i] >= target_pos: + slide_map[i] += 1 + slide_map[target_pos] = target_pos + + # Save the presentation + prs.save(output_path) + print(f"\nSaved rearranged presentation to: {output_path}") + print(f"Final presentation has {len(prs.slides)} slides") + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/pptx/scripts/replace.py b/account/admin/skills/pptx/scripts/replace.py new file mode 100644 index 0000000..8f7a8b1 --- /dev/null +++ b/account/admin/skills/pptx/scripts/replace.py @@ -0,0 +1,385 @@ +#!/usr/bin/env python3 +"""Apply text replacements to PowerPoint presentation. + +Usage: + python replace.py + +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 + + +def clear_paragraph_bullets(paragraph): + """Clear bullet formatting from a paragraph.""" + pPr = paragraph._element.get_or_add_pPr() + + # Remove existing bullet elements + for child in list(pPr): + if ( + child.tag.endswith("buChar") + or child.tag.endswith("buNone") + or child.tag.endswith("buAutoNum") + or child.tag.endswith("buFont") + ): + pPr.remove(child) + + return pPr + + +def apply_paragraph_properties(paragraph, para_data: Dict[str, Any]): + """Apply formatting properties to a paragraph.""" + # Get the text but don't set it on paragraph directly yet + text = para_data.get("text", "") + + # Get or create paragraph properties + pPr = clear_paragraph_bullets(paragraph) + + # Handle bullet formatting + if para_data.get("bullet", False): + level = para_data.get("level", 0) + paragraph.level = level + + # Calculate font-proportional indentation + font_size = para_data.get("font_size", 18.0) + level_indent_emu = int((font_size * (1.6 + level * 1.6)) * 12700) + hanging_indent_emu = int(-font_size * 0.8 * 12700) + + # Set indentation + pPr.attrib["marL"] = str(level_indent_emu) + pPr.attrib["indent"] = str(hanging_indent_emu) + + # Add bullet character + buChar = OxmlElement("a:buChar") + buChar.set("char", "•") + pPr.append(buChar) + + # Default to left alignment for bullets if not specified + if "alignment" not in para_data: + paragraph.alignment = PP_ALIGN.LEFT + else: + # Remove indentation for non-bullet text + pPr.attrib["marL"] = "0" + pPr.attrib["indent"] = "0" + + # Add buNone element + buNone = OxmlElement("a:buNone") + pPr.insert(0, buNone) + + # Apply alignment + if "alignment" in para_data: + alignment_map = { + "LEFT": PP_ALIGN.LEFT, + "CENTER": PP_ALIGN.CENTER, + "RIGHT": PP_ALIGN.RIGHT, + "JUSTIFY": PP_ALIGN.JUSTIFY, + } + if para_data["alignment"] in alignment_map: + paragraph.alignment = alignment_map[para_data["alignment"]] + + # Apply spacing + 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"]) + + # Apply run-level formatting + if not paragraph.runs: + run = paragraph.add_run() + run.text = text + else: + run = paragraph.runs[0] + run.text = text + + # Apply font properties + apply_font_properties(run, para_data) + + +def apply_font_properties(run, para_data: Dict[str, Any]): + """Apply font properties to a text run.""" + if "bold" in para_data: + run.font.bold = para_data["bold"] + if "italic" in para_data: + run.font.italic = para_data["italic"] + if "underline" in para_data: + run.font.underline = para_data["underline"] + 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"] + + # Apply color - prefer RGB, fall back to theme_color + if "color" in para_data: + color_hex = para_data["color"].lstrip("#") + if len(color_hex) == 6: + r = int(color_hex[0:2], 16) + g = int(color_hex[2:4], 16) + b = int(color_hex[4:6], 16) + run.font.color.rgb = RGBColor(r, g, b) + elif "theme_color" in para_data: + # Get theme color by name (e.g., "DARK_1", "ACCENT_1") + theme_name = para_data["theme_color"] + try: + run.font.color.theme_color = getattr(MSO_THEME_COLOR, theme_name) + except AttributeError: + print(f" WARNING: Unknown theme color name '{theme_name}'") + + +def detect_frame_overflow(inventory: InventoryData) -> Dict[str, Dict[str, float]]: + """Detect text overflow in shapes (text exceeding shape bounds). + + Returns dict of slide_key -> shape_key -> overflow_inches. + Only includes shapes that have text overflow. + """ + overflow_map = {} + + for slide_key, shapes_dict in inventory.items(): + for shape_key, shape_data in shapes_dict.items(): + # Check for frame overflow (text exceeding shape bounds) + if shape_data.frame_overflow_bottom is not None: + if slide_key not in overflow_map: + overflow_map[slide_key] = {} + overflow_map[slide_key][shape_key] = shape_data.frame_overflow_bottom + + return overflow_map + + +def validate_replacements(inventory: InventoryData, replacements: Dict) -> List[str]: + """Validate that all shapes in replacements exist in inventory. + + Returns list of error messages. + """ + errors = [] + + for slide_key, shapes_data in replacements.items(): + if not slide_key.startswith("slide-"): + continue + + # Check if slide exists + if slide_key not in inventory: + errors.append(f"Slide '{slide_key}' not found in inventory") + continue + + # Check each shape + for shape_key in shapes_data.keys(): + if shape_key not in inventory[slide_key]: + # Find shapes without replacements defined and show their content + unused_with_content = [] + for k in inventory[slide_key].keys(): + if k not in shapes_data: + shape_data = inventory[slide_key][k] + # Get text from paragraphs as preview + paragraphs = shape_data.paragraphs + if paragraphs and paragraphs[0].text: + first_text = paragraphs[0].text[:50] + if len(paragraphs[0].text) > 50: + first_text += "..." + unused_with_content.append(f"{k} ('{first_text}')") + else: + unused_with_content.append(k) + + errors.append( + f"Shape '{shape_key}' not found on '{slide_key}'. " + f"Shapes without replacements: {', '.join(sorted(unused_with_content)) if unused_with_content else 'none'}" + ) + + return errors + + +def check_duplicate_keys(pairs): + """Check for duplicate keys when loading JSON.""" + result = {} + for key, value in pairs: + if key in result: + raise ValueError(f"Duplicate key found in JSON: '{key}'") + result[key] = value + return result + + +def apply_replacements(pptx_file: str, json_file: str, output_file: str): + """Apply text replacements from JSON to PowerPoint presentation.""" + + # Load presentation + prs = Presentation(pptx_file) + + # Get inventory of all text shapes (returns ShapeData objects) + # Pass prs to use same Presentation instance + inventory = extract_text_inventory(Path(pptx_file), prs) + + # Detect text overflow in original presentation + original_overflow = detect_frame_overflow(inventory) + + # Load replacement data with duplicate key detection + with open(json_file, "r") as f: + replacements = json.load(f, object_pairs_hook=check_duplicate_keys) + + # Validate replacements + errors = validate_replacements(inventory, replacements) + if errors: + print("ERROR: Invalid shapes in replacement JSON:") + for error in errors: + print(f" - {error}") + print("\nPlease check the inventory and update your replacement JSON.") + print( + "You can regenerate the inventory with: python inventory.py " + ) + raise ValueError(f"Found {len(errors)} validation error(s)") + + # Track statistics + shapes_processed = 0 + shapes_cleared = 0 + shapes_replaced = 0 + + # Process each slide from inventory + for slide_key, shapes_dict in inventory.items(): + if not slide_key.startswith("slide-"): + continue + + slide_index = int(slide_key.split("-")[1]) + + if slide_index >= len(prs.slides): + print(f"Warning: Slide {slide_index} not found") + continue + + # Process each shape from inventory + for shape_key, shape_data in shapes_dict.items(): + shapes_processed += 1 + + # Get the shape directly from ShapeData + shape = shape_data.shape + if not shape: + print(f"Warning: {shape_key} has no shape reference") + continue + + # ShapeData already validates text_frame in __init__ + text_frame = shape.text_frame # type: ignore + + text_frame.clear() # type: ignore + shapes_cleared += 1 + + # Check for replacement paragraphs + replacement_shape_data = replacements.get(slide_key, {}).get(shape_key, {}) + if "paragraphs" not in replacement_shape_data: + continue + + shapes_replaced += 1 + + # Add replacement paragraphs + for i, para_data in enumerate(replacement_shape_data["paragraphs"]): + if i == 0: + p = text_frame.paragraphs[0] # type: ignore + else: + p = text_frame.add_paragraph() # type: ignore + + apply_paragraph_properties(p, para_data) + + # Check for issues after replacements + # Save to a temporary file and reload to avoid modifying the presentation during inventory + # (extract_text_inventory accesses font.color which adds empty elements) + import tempfile + + with tempfile.NamedTemporaryFile(suffix=".pptx", delete=False) as tmp: + tmp_path = Path(tmp.name) + prs.save(str(tmp_path)) + + try: + updated_inventory = extract_text_inventory(tmp_path) + updated_overflow = detect_frame_overflow(updated_inventory) + finally: + tmp_path.unlink() # Clean up temp file + + # Check if any text overflow got worse + overflow_errors = [] + for slide_key, shape_overflows in updated_overflow.items(): + for shape_key, new_overflow in shape_overflows.items(): + # Get original overflow (0 if there was no overflow before) + original = original_overflow.get(slide_key, {}).get(shape_key, 0.0) + + # Error if overflow increased + if new_overflow > original + 0.01: # Small tolerance for rounding + increase = new_overflow - original + overflow_errors.append( + f'{slide_key}/{shape_key}: overflow worsened by {increase:.2f}" ' + f'(was {original:.2f}", now {new_overflow:.2f}")' + ) + + # Collect warnings from updated shapes + warnings = [] + for slide_key, shapes_dict in updated_inventory.items(): + for shape_key, shape_data in shapes_dict.items(): + if shape_data.warnings: + for warning in shape_data.warnings: + warnings.append(f"{slide_key}/{shape_key}: {warning}") + + # Fail if there are any issues + if overflow_errors or warnings: + print("\nERROR: Issues detected in replacement output:") + if overflow_errors: + print("\nText overflow worsened:") + for error in overflow_errors: + print(f" - {error}") + if warnings: + print("\nFormatting warnings:") + for warning in warnings: + print(f" - {warning}") + print("\nPlease fix these issues before saving.") + raise ValueError( + f"Found {len(overflow_errors)} overflow error(s) and {len(warnings)} warning(s)" + ) + + # Save the presentation + prs.save(output_file) + + # Report results + print(f"Saved updated presentation to: {output_file}") + print(f"Processed {len(prs.slides)} slides") + print(f" - Shapes processed: {shapes_processed}") + print(f" - Shapes cleared: {shapes_cleared}") + print(f" - Shapes replaced: {shapes_replaced}") + + +def main(): + """Main entry point for command-line usage.""" + if len(sys.argv) != 4: + print(__doc__) + sys.exit(1) + + input_pptx = Path(sys.argv[1]) + replacements_json = Path(sys.argv[2]) + output_pptx = Path(sys.argv[3]) + + if not input_pptx.exists(): + print(f"Error: Input file '{input_pptx}' not found") + sys.exit(1) + + if not replacements_json.exists(): + print(f"Error: Replacements JSON file '{replacements_json}' not found") + sys.exit(1) + + try: + apply_replacements(str(input_pptx), str(replacements_json), str(output_pptx)) + except Exception as e: + print(f"Error applying replacements: {e}") + import traceback + + traceback.print_exc() + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/pptx/scripts/thumbnail.py b/account/admin/skills/pptx/scripts/thumbnail.py new file mode 100644 index 0000000..edcbdc0 --- /dev/null +++ b/account/admin/skills/pptx/scripts/thumbnail.py @@ -0,0 +1,289 @@ +"""Create thumbnail grids from PowerPoint presentation slides. + +Creates a grid layout of slide thumbnails for quick visual analysis. +Labels each thumbnail with its XML filename (e.g., slide1.xml). +Hidden slides are shown with a placeholder pattern. + +Usage: + python thumbnail.py input.pptx [output_prefix] [--cols N] + +Examples: + python thumbnail.py presentation.pptx + # Creates: thumbnails.jpg + + python thumbnail.py template.pptx grid --cols 4 + # Creates: grid.jpg (or grid-1.jpg, grid-2.jpg for large decks) +""" + +import argparse +import subprocess +import sys +import tempfile +import zipfile +from pathlib import Path + +import defusedxml.minidom +from office.soffice import get_soffice_env +from PIL import Image, ImageDraw, ImageFont + +THUMBNAIL_WIDTH = 300 +CONVERSION_DPI = 100 +MAX_COLS = 6 +DEFAULT_COLS = 3 +JPEG_QUALITY = 95 +GRID_PADDING = 20 +BORDER_WIDTH = 2 +FONT_SIZE_RATIO = 0.10 +LABEL_PADDING_RATIO = 0.4 + + +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)", + ) + parser.add_argument( + "--cols", + type=int, + default=DEFAULT_COLS, + help=f"Number of columns (default: {DEFAULT_COLS}, max: {MAX_COLS})", + ) + + args = parser.parse_args() + + cols = min(args.cols, MAX_COLS) + if args.cols > MAX_COLS: + print(f"Warning: Columns limited to {MAX_COLS}") + + input_path = Path(args.input) + if not input_path.exists() or input_path.suffix.lower() != ".pptx": + print(f"Error: Invalid PowerPoint file: {args.input}", file=sys.stderr) + sys.exit(1) + + output_path = Path(f"{args.output_prefix}.jpg") + + try: + slide_info = get_slide_info(input_path) + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + visible_images = convert_to_images(input_path, temp_path) + + if not visible_images and not any(s["hidden"] for s in slide_info): + print("Error: No slides found", file=sys.stderr) + sys.exit(1) + + slides = build_slide_list(slide_info, visible_images, temp_path) + + grid_files = create_grids(slides, cols, THUMBNAIL_WIDTH, output_path) + + print(f"Created {len(grid_files)} grid(s):") + for grid_file in grid_files: + print(f" {grid_file}") + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) + + +def get_slide_info(pptx_path: Path) -> list[dict]: + with zipfile.ZipFile(pptx_path, "r") as zf: + rels_content = zf.read("ppt/_rels/presentation.xml.rels").decode("utf-8") + rels_dom = defusedxml.minidom.parseString(rels_content) + + rid_to_slide = {} + for rel in rels_dom.getElementsByTagName("Relationship"): + rid = rel.getAttribute("Id") + target = rel.getAttribute("Target") + rel_type = rel.getAttribute("Type") + if "slide" in rel_type and target.startswith("slides/"): + rid_to_slide[rid] = target.replace("slides/", "") + + pres_content = zf.read("ppt/presentation.xml").decode("utf-8") + pres_dom = defusedxml.minidom.parseString(pres_content) + + slides = [] + for sld_id in pres_dom.getElementsByTagName("p:sldId"): + rid = sld_id.getAttribute("r:id") + if rid in rid_to_slide: + hidden = sld_id.getAttribute("show") == "0" + slides.append({"name": rid_to_slide[rid], "hidden": hidden}) + + return slides + + +def build_slide_list( + slide_info: list[dict], + visible_images: list[Path], + temp_dir: Path, +) -> list[tuple[Path, str]]: + if visible_images: + with Image.open(visible_images[0]) as img: + placeholder_size = img.size + else: + placeholder_size = (1920, 1080) + + slides = [] + visible_idx = 0 + + for info in slide_info: + if info["hidden"]: + placeholder_path = temp_dir / f"hidden-{info['name']}.jpg" + placeholder_img = create_hidden_placeholder(placeholder_size) + placeholder_img.save(placeholder_path, "JPEG") + slides.append((placeholder_path, f"{info['name']} (hidden)")) + else: + if visible_idx < len(visible_images): + slides.append((visible_images[visible_idx], info["name"])) + visible_idx += 1 + + return slides + + +def create_hidden_placeholder(size: tuple[int, int]) -> Image.Image: + 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 convert_to_images(pptx_path: Path, temp_dir: Path) -> list[Path]: + 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, + env=get_soffice_env(), + ) + if result.returncode != 0 or not pdf_path.exists(): + raise RuntimeError("PDF conversion failed") + + result = subprocess.run( + [ + "pdftoppm", + "-jpeg", + "-r", + str(CONVERSION_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 create_grids( + slides: list[tuple[Path, str]], + cols: int, + width: int, + output_path: Path, +) -> list[str]: + max_per_grid = cols * (cols + 1) + grid_files = [] + + for chunk_idx, start_idx in enumerate(range(0, len(slides), max_per_grid)): + end_idx = min(start_idx + max_per_grid, len(slides)) + chunk_slides = slides[start_idx:end_idx] + + grid = create_grid(chunk_slides, cols, width) + + if len(slides) <= max_per_grid: + grid_filename = output_path + else: + stem = output_path.stem + suffix = output_path.suffix + grid_filename = output_path.parent / f"{stem}-{chunk_idx + 1}{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( + slides: list[tuple[Path, str]], + cols: int, + width: int, +) -> Image.Image: + font_size = int(width * FONT_SIZE_RATIO) + label_padding = int(font_size * LABEL_PADDING_RATIO) + + with Image.open(slides[0][0]) as img: + aspect = img.height / img.width + height = int(width * aspect) + + rows = (len(slides) + 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, slide_name) in enumerate(slides): + 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 = slide_name + 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: + 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() diff --git a/account/admin/skills/pretty-mermaid/.openakita-i18n.json b/account/admin/skills/pretty-mermaid/.openakita-i18n.json new file mode 100644 index 0000000..83fdbbd --- /dev/null +++ b/account/admin/skills/pretty-mermaid/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Mermaid 专业图表", + "description": "生成专业 Mermaid 图表,支持多主题(Tokyo Night、Dracula、GitHub Light)、SVG/ASCII 输出、批量渲染和模板库。" + } +} diff --git a/account/admin/skills/pretty-mermaid/SKILL.md b/account/admin/skills/pretty-mermaid/SKILL.md new file mode 100644 index 0000000..31aa1d0 --- /dev/null +++ b/account/admin/skills/pretty-mermaid/SKILL.md @@ -0,0 +1,579 @@ +--- +name: openakita/skills@pretty-mermaid +description: Generate professional Mermaid diagrams with multiple themes, SVG/ASCII output, batch rendering, and a built-in template library for common diagram patterns. Supports flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, C4 architecture, and Gantt charts. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Pretty Mermaid — 专业 Mermaid 图表生成 + +## When to Use + +- 用户要求创建流程图、架构图、时序图、类图、状态图、ER 图、C4 架构图或甘特图 +- 需要将图表渲染为 SVG 或 ASCII 文本输出 +- 需要批量生成多张图表 +- 用户要求使用特定主题或配色方案 +- 需要可复用的图表模板 + +--- + +## Prerequisites + +### 必需工具 + +| 工具 | 用途 | 安装方式 | +|------|------|---------| +| Node.js ≥ 18 | 运行 Mermaid CLI | 系统预装或 `nvm install 18` | +| `@mermaid-js/mermaid-cli` | 渲染 SVG/PNG | `npm install -g @mermaid-js/mermaid-cli` | + +### 可选工具 + +| 工具 | 用途 | 安装方式 | +|------|------|---------| +| `monodraw` (macOS) | ASCII 图表编辑 | App Store | +| `graph-easy` | ASCII 渲染 | `cpan Graph::Easy` | + +### 验证安装 + +```bash +mmdc --version +``` + +如果 `mmdc` 不可用,回退到纯 Mermaid 代码块输出,让用户在支持 Mermaid 的编辑器或浏览器中预览。 + +--- + +## Instructions + +### 核心工作流 + +1. **理解需求** — 明确图表类型、数据来源、目标受众 +2. **选择图表类型** — 根据场景匹配最合适的 Mermaid 图表 +3. **选择主题** — 根据使用场景选择配色方案 +4. **编写 Mermaid 代码** — 遵循可读性最佳实践 +5. **渲染输出** — 按指定格式输出 SVG、PNG 或 ASCII +6. **校验与优化** — 检查语法、布局、可读性 + +### 图表类型选择指南 + +| 场景 | 推荐图表 | Mermaid 关键字 | +|------|---------|---------------| +| 业务流程、审批流 | 流程图 | `flowchart TD/LR` | +| API 调用、服务交互 | 时序图 | `sequenceDiagram` | +| 代码结构、OOP 设计 | 类图 | `classDiagram` | +| 生命周期、状态机 | 状态图 | `stateDiagram-v2` | +| 数据库设计 | ER 图 | `erDiagram` | +| 系统架构、微服务 | C4 架构图 | `C4Context/C4Container/C4Component` | +| 项目排期、里程碑 | 甘特图 | `gantt` | +| Git 分支策略 | Git 图 | `gitGraph` | +| 思维导图、脑暴 | 思维导图 | `mindmap` | +| 时间线 | 时间线 | `timeline` | + +--- + +## Workflows + +### Workflow 1: 单张图表生成 + +**步骤 1 — 收集信息** + +向用户确认以下内容(如未提供则使用默认值): + +| 参数 | 默认值 | 可选值 | +|------|--------|-------| +| 图表类型 | flowchart | 见上方选择指南 | +| 方向 | TD(上到下) | TD, LR, RL, BT | +| 主题 | default | default, dark, forest, neutral, base | +| 输出格式 | Mermaid 代码块 | svg, png, ascii, mermaid | +| 主题方案 | Tokyo Night | Tokyo Night, Dracula, GitHub Light, Nord, Solarized | + +**步骤 2 — 编写 Mermaid 代码** + +遵循以下规范: + +``` +%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1b26', 'primaryTextColor': '#a9b1d6', 'primaryBorderColor': '#7aa2f7', 'lineColor': '#565f89', 'secondaryColor': '#24283b', 'tertiaryColor': '#1a1b26' }}}%% +flowchart TD + A[开始] --> B{条件判断} + B -->|是| C[执行操作] + B -->|否| D[跳过] + C --> E[结束] + D --> E +``` + +**步骤 3 — 渲染(如需 SVG/PNG)** + +将 Mermaid 代码写入临时 `.mmd` 文件,然后调用: + +```bash +mmdc -i diagram.mmd -o diagram.svg -t dark -b transparent +mmdc -i diagram.mmd -o diagram.png -t dark -b white -w 1200 +``` + +**步骤 4 — 输出** + +返回渲染后的文件路径,或直接在消息中嵌入 Mermaid 代码块。 + +--- + +### Workflow 2: 批量图表生成 + +适用于一次性生成多张相关图表(如系统设计文档)。 + +**步骤 1** — 收集所有图表的需求列表 + +**步骤 2** — 创建批处理配置: + +```json +{ + "theme": "tokyo-night", + "outputDir": "./diagrams", + "outputFormat": "svg", + "diagrams": [ + { + "name": "system-overview", + "type": "C4Context", + "title": "系统总览" + }, + { + "name": "api-sequence", + "type": "sequenceDiagram", + "title": "API 调用时序" + }, + { + "name": "data-model", + "type": "erDiagram", + "title": "数据模型" + } + ] +} +``` + +**步骤 3** — 逐一生成 Mermaid 代码并渲染 + +**步骤 4** — 返回所有图表的路径和预览 + +--- + +### Workflow 3: ASCII 图表输出 + +当用户需要纯文本图表(用于 CLI、日志、README 等场景): + +**方法 A — 手动 ASCII 绘制** + +对于简单图表,直接使用字符绘制: + +``` +┌─────────┐ ┌─────────┐ ┌─────────┐ +│ Client │────▶│ Server │────▶│Database │ +└─────────┘ └─────────┘ └─────────┘ + │ + ▼ + ┌─────────┐ + │ Cache │ + └─────────┘ +``` + +**方法 B — 使用 graph-easy 转换** + +```bash +echo "[ Client ] -> [ Server ] -> [ Database ]" | graph-easy --as=ascii +``` + +--- + +## 主题配置 + +### Tokyo Night(默认) + +``` +%%{init: {'theme': 'base', 'themeVariables': { + 'primaryColor': '#1a1b26', + 'primaryTextColor': '#a9b1d6', + 'primaryBorderColor': '#7aa2f7', + 'lineColor': '#565f89', + 'secondaryColor': '#24283b', + 'tertiaryColor': '#414868', + 'noteBkgColor': '#1a1b26', + 'noteTextColor': '#c0caf5', + 'noteBorderColor': '#7aa2f7' +}}}%% +``` + +### Dracula + +``` +%%{init: {'theme': 'base', 'themeVariables': { + 'primaryColor': '#282a36', + 'primaryTextColor': '#f8f8f2', + 'primaryBorderColor': '#bd93f9', + 'lineColor': '#6272a4', + 'secondaryColor': '#44475a', + 'tertiaryColor': '#383a59', + 'noteBkgColor': '#282a36', + 'noteTextColor': '#f8f8f2', + 'noteBorderColor': '#ff79c6' +}}}%% +``` + +### GitHub Light + +``` +%%{init: {'theme': 'base', 'themeVariables': { + 'primaryColor': '#ffffff', + 'primaryTextColor': '#24292f', + 'primaryBorderColor': '#d0d7de', + 'lineColor': '#656d76', + 'secondaryColor': '#f6f8fa', + 'tertiaryColor': '#eaeef2', + 'noteBkgColor': '#ddf4ff', + 'noteTextColor': '#24292f', + 'noteBorderColor': '#54aeff' +}}}%% +``` + +### Nord + +``` +%%{init: {'theme': 'base', 'themeVariables': { + 'primaryColor': '#2e3440', + 'primaryTextColor': '#eceff4', + 'primaryBorderColor': '#88c0d0', + 'lineColor': '#4c566a', + 'secondaryColor': '#3b4252', + 'tertiaryColor': '#434c5e', + 'noteBkgColor': '#2e3440', + 'noteTextColor': '#eceff4', + 'noteBorderColor': '#81a1c1' +}}}%% +``` + +### Solarized + +``` +%%{init: {'theme': 'base', 'themeVariables': { + 'primaryColor': '#002b36', + 'primaryTextColor': '#839496', + 'primaryBorderColor': '#268bd2', + 'lineColor': '#586e75', + 'secondaryColor': '#073642', + 'tertiaryColor': '#073642', + 'noteBkgColor': '#002b36', + 'noteTextColor': '#93a1a1', + 'noteBorderColor': '#2aa198' +}}}%% +``` + +--- + +## 模板库 + +### 模板 1: 微服务架构(C4 Container) + +```mermaid +C4Container + title 微服务系统架构 + + Person(user, "用户", "通过浏览器或移动端访问系统") + + System_Boundary(system, "核心系统") { + Container(web, "Web 前端", "React", "用户界面") + Container(gateway, "API 网关", "Kong/Nginx", "路由、限流、鉴权") + Container(auth, "认证服务", "Go", "JWT 签发与验证") + Container(biz, "业务服务", "Python", "核心业务逻辑") + Container(notify, "通知服务", "Node.js", "邮件/短信/推送") + ContainerDb(db, "主数据库", "PostgreSQL", "业务数据存储") + ContainerDb(cache, "缓存", "Redis", "会话与热数据缓存") + ContainerQueue(mq, "消息队列", "RabbitMQ", "异步任务处理") + } + + Rel(user, web, "使用", "HTTPS") + Rel(web, gateway, "API 调用", "HTTPS") + Rel(gateway, auth, "鉴权", "gRPC") + Rel(gateway, biz, "业务请求", "gRPC") + Rel(biz, db, "读写", "TCP") + Rel(biz, cache, "缓存", "TCP") + Rel(biz, mq, "发布消息", "AMQP") + Rel(mq, notify, "消费消息", "AMQP") +``` + +### 模板 2: CI/CD 流水线(Flowchart) + +```mermaid +flowchart LR + A[代码提交] --> B[触发 CI] + B --> C{代码检查} + C -->|通过| D[单元测试] + C -->|失败| Z[通知开发者] + D -->|通过| E[构建镜像] + D -->|失败| Z + E --> F[推送镜像仓库] + F --> G{环境选择} + G -->|Staging| H[部署 Staging] + G -->|Production| I[人工审批] + I -->|批准| J[蓝绿部署] + I -->|拒绝| Z + H --> K[集成测试] + K -->|通过| L[✅ Staging 就绪] + K -->|失败| M[自动回滚] + J --> N[健康检查] + N -->|通过| O[✅ 上线成功] + N -->|失败| P[自动回滚] +``` + +### 模板 3: 用户认证时序(Sequence) + +```mermaid +sequenceDiagram + actor U as 用户 + participant C as 客户端 + participant G as API 网关 + participant A as 认证服务 + participant D as 数据库 + + U->>C: 输入用户名/密码 + C->>G: POST /api/auth/login + G->>A: 转发认证请求 + A->>D: 查询用户记录 + D-->>A: 返回用户数据 + alt 密码正确 + A->>A: 生成 JWT Token + A-->>G: 200 OK + Token + G-->>C: 返回 Token + C->>C: 存储 Token + C-->>U: 登录成功 + else 密码错误 + A-->>G: 401 Unauthorized + G-->>C: 认证失败 + C-->>U: 提示错误 + end + + Note over C,G: 后续请求携带 Token + U->>C: 访问受保护资源 + C->>G: GET /api/data (Bearer Token) + G->>A: 验证 Token + A-->>G: Token 有效 + G->>G: 转发到业务服务 +``` + +### 模板 4: 数据库 ER 图 + +```mermaid +erDiagram + USER ||--o{ ORDER : places + USER { + int id PK + string username UK + string email UK + string password_hash + datetime created_at + datetime updated_at + } + ORDER ||--|{ ORDER_ITEM : contains + ORDER { + int id PK + int user_id FK + decimal total_amount + string status + datetime created_at + } + ORDER_ITEM }|--|| PRODUCT : references + ORDER_ITEM { + int id PK + int order_id FK + int product_id FK + int quantity + decimal unit_price + } + PRODUCT ||--o{ PRODUCT_TAG : has + PRODUCT { + int id PK + string name + text description + decimal price + int stock + } + TAG ||--o{ PRODUCT_TAG : applied + TAG { + int id PK + string name UK + } + PRODUCT_TAG { + int product_id FK + int tag_id FK + } +``` + +### 模板 5: 项目甘特图 + +```mermaid +gantt + title 项目开发排期 + dateFormat YYYY-MM-DD + axisFormat %m/%d + + section 需求阶段 + 需求调研 :done, req1, 2025-01-01, 7d + 需求评审 :done, req2, after req1, 3d + PRD 定稿 :done, req3, after req2, 2d + + section 设计阶段 + 技术方案设计 :active, des1, after req3, 5d + UI/UX 设计 : des2, after req3, 7d + 设计评审 : des3, after des2, 2d + + section 开发阶段 + 后端开发 : dev1, after des1, 15d + 前端开发 : dev2, after des3, 15d + 联调测试 : dev3, after dev1, 5d + + section 发布阶段 + UAT 测试 : rel1, after dev3, 5d + 修复 Bug : rel2, after rel1, 3d + 正式发布 :milestone, rel3, after rel2, 0d +``` + +--- + +## Output Format + +### 默认输出 + +直接在回复中使用 Mermaid 代码块: + +```` +```mermaid +flowchart TD + A --> B +``` +```` + +### SVG 文件 + +```bash +mmdc -i input.mmd -o output.svg -t dark -b transparent --cssFile custom.css +``` + +### PNG 文件 + +```bash +mmdc -i input.mmd -o output.png -t dark -b white -w 1920 -H 1080 -s 2 +``` + +参数说明: +- `-t` 主题:default, dark, forest, neutral +- `-b` 背景色:transparent, white, #hex +- `-w` 宽度(像素) +- `-H` 高度(像素) +- `-s` 缩放倍数 + +### ASCII 文本 + +直接使用字符绘制,适合嵌入代码注释、终端输出、纯文本文档。 + +--- + +## Common Pitfalls + +### 1. 节点 ID 冲突 + +**错误**:在同一图表中使用重复的节点 ID + +```mermaid +flowchart TD + A[登录] --> B[验证] + A[注册] --> B[检查] +``` + +**正确**:使用唯一 ID + +```mermaid +flowchart TD + login[登录] --> validate[验证] + register[注册] --> check[检查] +``` + +### 2. 特殊字符未转义 + +**错误**:节点文本包含括号、引号等 + +``` +A[用户输入(name)] +``` + +**正确**:使用引号包裹 + +``` +A["用户输入(name)"] +``` + +### 3. 图表过于复杂 + +单张图表超过 20 个节点时,考虑拆分为多张子图: + +```mermaid +flowchart TD + subgraph 前端 + A --> B --> C + end + subgraph 后端 + D --> E --> F + end + C --> D +``` + +### 4. 方向选择不当 + +- 层级结构(组织架构、决策树)→ **TD**(上到下) +- 流程/管道 → **LR**(左到右) +- 时间线/历史 → **LR** +- 请求-响应 → **TD** 或 **LR** + +### 5. 中文乱码 + +渲染 SVG/PNG 时如果出现中文乱码,使用 `--cssFile` 指定字体: + +```css +* { + font-family: "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", sans-serif; +} +``` + +### 6. Mermaid CLI 超时 + +大型图表可能渲染超时,增加超时参数: + +```bash +mmdc -i large-diagram.mmd -o output.svg --puppeteerConfigFile puppeteer.json +``` + +`puppeteer.json`: +```json +{ + "timeout": 60000 +} +``` + +### 7. 子图嵌套限制 + +Mermaid 支持子图嵌套,但过深的嵌套(超过 3 层)可能导致渲染异常。保持层级扁平化。 + +--- + +## 最佳实践 + +1. **命名规范** — 节点 ID 使用有意义的英文命名,显示文本使用中文 +2. **布局控制** — 善用 `subgraph` 对节点分组,改善布局 +3. **颜色语义** — 绿色表示成功、红色表示失败、蓝色表示进行中 +4. **注释标注** — 使用 `Note` 添加关键说明 +5. **渐进呈现** — 复杂系统先画总览再画细节,用 C4 的 Context → Container → Component 层级 +6. **版本控制** — Mermaid 代码是纯文本,适合纳入 Git 管理 +7. **一致性** — 同一文档中的所有图表使用相同主题配置 + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加自定义主题和模板,Agent 会自动合并使用。 diff --git a/account/admin/skills/skill-creator/LICENSE.txt b/account/admin/skills/skill-creator/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/skill-creator/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/skill-creator/SKILL.md b/account/admin/skills/skill-creator/SKILL.md new file mode 100644 index 0000000..353fc0a --- /dev/null +++ b/account/admin/skills/skill-creator/SKILL.md @@ -0,0 +1,90 @@ +--- +name: openakita/skills@skill-creator +description: 创建和改进 OpenAkita 技能。当需要:(1) 为重复性任务创建新技能,(2) 改进现有技能,(3) 将临时脚本封装为可复用技能时使用。技能是 OpenAkita 自进化的核心机制。 +--- + +# Skill Creator — OpenAkita 技能创建指南 + +## 技能是什么 + +技能是模块化的、自包含的能力包,通过 SKILL.md 定义,扩展 OpenAkita 的能力。每个技能包含: +- `SKILL.md`(必需):YAML frontmatter(name + description)+ Markdown 指令 +- `scripts/`(可选):可执行脚本(Python/Bash) +- `references/`(可选):参考文档 +- `assets/`(可选):模板、图片等资源文件 + +## 何时创建技能 + +1. 同类操作第二次出现(持久化规则) +2. 用户明确要求创建技能 +3. 任务涉及复杂多步流程且可能复用 +4. 现有临时脚本需要升级为可复用能力 + +## 创建流程 + +### 1. 确定技能范围 + +明确技能要解决什么问题、触发条件是什么、需要哪些资源。 + +### 2. 创建技能目录 + +在 `skills/` 下创建目录: + +``` +skills/{skill-name}/ +├── SKILL.md # 必需:技能定义 +├── .openakita-i18n.json # 推荐:中文名和中文描述 +├── scripts/ # 可选:可执行脚本 +├── references/ # 可选:参考文档 +└── assets/ # 可选:模板等资源 +``` + +### 3. 编写 SKILL.md + +**Frontmatter(必需)**: +```yaml +--- +name: skill-name +description: 清晰描述技能功能和触发条件。description 是触发机制,必须说明"做什么"和"何时用"。 +--- +``` + +### 3.5 创建中文翻译文件(推荐) + +在技能目录下创建 `.openakita-i18n.json`,提供中文显示名和描述: +```json +{ + "zh": { + "name": "技能中文名(2-6个字)", + "description": "技能功能的中文描述,简洁通顺。" + } +} +``` +此文件让中文用户在界面上看到友好的中文名称和说明。 + +**正文**:使用 Markdown 编写使用指令。原则: +- OpenAkita 已经很聪明,只写它不知道的信息 +- 简洁优先,示例优于冗长解释 +- 正文控制在 500 行以内,超出部分拆到 references/ + +### 4. 编写脚本(如需要) + +将确定性操作封装为 `scripts/` 下的脚本: +- 脚本必须实际运行测试,确保无 bug +- 使用 `run_skill_script` 执行 + +### 5. 加载技能 + +创建完成后,使用 `load_skill` 将技能加载到系统中,使其在技能清单中可见。 + +## 改进现有技能 + +1. 使用 `get_skill_info` 查看当前技能内容 +2. 修改 SKILL.md 或脚本文件 +3. 使用 `reload_skill` 重新加载 + +## 关键原则 + +- **上下文窗口是公共资源**:技能与系统提示词、对话历史共享上下文,每一行都要值得其 token 开销 +- **渐进式披露**:frontmatter 始终可见(~100词),正文仅在技能触发后加载,脚本按需执行 +- **不要创建多余文件**:不需要 README.md、CHANGELOG.md 等辅助文件 diff --git a/account/admin/skills/skill-creator/references/output-patterns.md b/account/admin/skills/skill-creator/references/output-patterns.md new file mode 100644 index 0000000..073ddda --- /dev/null +++ b/account/admin/skills/skill-creator/references/output-patterns.md @@ -0,0 +1,82 @@ +# Output Patterns + +Use these patterns when skills need to produce consistent, high-quality output. + +## Template Pattern + +Provide templates for output format. Match the level of strictness to your needs. + +**For strict requirements (like API responses or data formats):** + +```markdown +## Report structure + +ALWAYS use this exact template structure: + +# [Analysis Title] + +## Executive summary +[One-paragraph overview of key findings] + +## Key findings +- Finding 1 with supporting data +- Finding 2 with supporting data +- Finding 3 with supporting data + +## Recommendations +1. Specific actionable recommendation +2. Specific actionable recommendation +``` + +**For flexible guidance (when adaptation is useful):** + +```markdown +## Report structure + +Here is a sensible default format, but use your best judgment: + +# [Analysis Title] + +## Executive summary +[Overview] + +## Key findings +[Adapt sections based on what you discover] + +## Recommendations +[Tailor to the specific context] + +Adjust sections as needed for the specific analysis type. +``` + +## Examples Pattern + +For skills where output quality depends on seeing examples, provide input/output pairs: + +```markdown +## Commit message format + +Generate commit messages following these examples: + +**Example 1:** +Input: Added user authentication with JWT tokens +Output: +``` +feat(auth): implement JWT-based authentication + +Add login endpoint and token validation middleware +``` + +**Example 2:** +Input: Fixed bug where dates displayed incorrectly in reports +Output: +``` +fix(reports): correct date formatting in timezone conversion + +Use UTC timestamps consistently across report generation +``` + +Follow this style: type(scope): brief description, then detailed explanation. +``` + +Examples help Claude understand the desired style and level of detail more clearly than descriptions alone. diff --git a/account/admin/skills/skill-creator/references/workflows.md b/account/admin/skills/skill-creator/references/workflows.md new file mode 100644 index 0000000..a350c3c --- /dev/null +++ b/account/admin/skills/skill-creator/references/workflows.md @@ -0,0 +1,28 @@ +# Workflow Patterns + +## Sequential Workflows + +For complex tasks, break operations into clear, sequential steps. It is often helpful to give Claude an overview of the process towards the beginning of SKILL.md: + +```markdown +Filling a PDF form involves these steps: + +1. Analyze the form (run analyze_form.py) +2. Create field mapping (edit fields.json) +3. Validate mapping (run validate_fields.py) +4. Fill the form (run fill_form.py) +5. Verify output (run verify_output.py) +``` + +## Conditional Workflows + +For tasks with branching logic, guide Claude through decision points: + +```markdown +1. Determine the modification type: + **Creating new content?** → Follow "Creation workflow" below + **Editing existing content?** → Follow "Editing workflow" below + +2. Creation workflow: [steps] +3. Editing workflow: [steps] +``` \ No newline at end of file diff --git a/account/admin/skills/skill-creator/scripts/init_skill.py b/account/admin/skills/skill-creator/scripts/init_skill.py new file mode 100644 index 0000000..13e86b0 --- /dev/null +++ b/account/admin/skills/skill-creator/scripts/init_skill.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python3 +""" +Skill Initializer - Creates a new skill from template + +Usage: + init_skill.py --path + +Examples: + init_skill.py my-new-skill --path skills/public + init_skill.py my-api-helper --path skills/private + init_skill.py custom-skill --path /custom/location +""" + +import json +import sys +from pathlib import Path + + +SKILL_TEMPLATE = """--- +name: {skill_name} +description: [TODO: Complete and informative explanation of what the skill does and when to use it. Include WHEN to use this skill - specific scenarios, file types, or tasks that trigger it.] +--- + +# {skill_title} + +## Overview + +[TODO: 1-2 sentences explaining what this skill enables] + +## Structuring This Skill + +[TODO: Choose the structure that best fits this skill's purpose. Common patterns: + +**1. Workflow-Based** (best for sequential processes) +- Works well when there are clear step-by-step procedures +- Example: DOCX skill with "Workflow Decision Tree" → "Reading" → "Creating" → "Editing" +- Structure: ## Overview → ## Workflow Decision Tree → ## Step 1 → ## Step 2... + +**2. Task-Based** (best for tool collections) +- Works well when the skill offers different operations/capabilities +- Example: PDF skill with "Quick Start" → "Merge PDFs" → "Split PDFs" → "Extract Text" +- Structure: ## Overview → ## Quick Start → ## Task Category 1 → ## Task Category 2... + +**3. Reference/Guidelines** (best for standards or specifications) +- Works well for brand guidelines, coding standards, or requirements +- Example: Brand styling with "Brand Guidelines" → "Colors" → "Typography" → "Features" +- Structure: ## Overview → ## Guidelines → ## Specifications → ## Usage... + +**4. Capabilities-Based** (best for integrated systems) +- Works well when the skill provides multiple interrelated features +- Example: Product Management with "Core Capabilities" → numbered capability list +- Structure: ## Overview → ## Core Capabilities → ### 1. Feature → ### 2. Feature... + +Patterns can be mixed and matched as needed. Most skills combine patterns (e.g., start with task-based, add workflow for complex operations). + +Delete this entire "Structuring This Skill" section when done - it's just guidance.] + +## [TODO: Replace with the first main section based on chosen structure] + +[TODO: Add content here. See examples in existing skills: +- Code samples for technical skills +- Decision trees for complex workflows +- Concrete examples with realistic user requests +- References to scripts/templates/references as needed] + +## Resources + +This skill includes example resource directories that demonstrate how to organize different types of bundled resources: + +### scripts/ +Executable code (Python/Bash/etc.) that can be run directly to perform specific operations. + +**Examples from other skills:** +- PDF skill: `fill_fillable_fields.py`, `extract_form_field_info.py` - utilities for PDF manipulation +- DOCX skill: `document.py`, `utilities.py` - Python modules for document processing + +**Appropriate for:** Python scripts, shell scripts, or any executable code that performs automation, data processing, or specific operations. + +**Note:** Scripts may be executed without loading into context, but can still be read by Claude for patching or environment adjustments. + +### references/ +Documentation and reference material intended to be loaded into context to inform Claude's process and thinking. + +**Examples from other skills:** +- Product management: `communication.md`, `context_building.md` - detailed workflow guides +- BigQuery: API reference documentation and query examples +- Finance: Schema documentation, company policies + +**Appropriate for:** In-depth documentation, API references, database schemas, comprehensive guides, or any detailed information that Claude should reference while working. + +### assets/ +Files not intended to be loaded into context, but rather used within the output Claude produces. + +**Examples from other skills:** +- Brand styling: PowerPoint template files (.pptx), logo files +- Frontend builder: HTML/React boilerplate project directories +- Typography: Font files (.ttf, .woff2) + +**Appropriate for:** Templates, boilerplate code, document templates, images, icons, fonts, or any files meant to be copied or used in the final output. + +--- + +**Any unneeded directories can be deleted.** Not every skill requires all three types of resources. +""" + +EXAMPLE_SCRIPT = '''#!/usr/bin/env python3 +""" +Example helper script for {skill_name} + +This is a placeholder script that can be executed directly. +Replace with actual implementation or delete if not needed. + +Example real scripts from other skills: +- pdf/scripts/fill_fillable_fields.py - Fills PDF form fields +- pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images +""" + +def main(): + print("This is an example script for {skill_name}") + # TODO: Add actual script logic here + # This could be data processing, file conversion, API calls, etc. + +if __name__ == "__main__": + main() +''' + +EXAMPLE_REFERENCE = """# Reference Documentation for {skill_title} + +This is a placeholder for detailed reference documentation. +Replace with actual reference content or delete if not needed. + +Example real reference docs from other skills: +- product-management/references/communication.md - Comprehensive guide for status updates +- product-management/references/context_building.md - Deep-dive on gathering context +- bigquery/references/ - API references and query examples + +## When Reference Docs Are Useful + +Reference docs are ideal for: +- Comprehensive API documentation +- Detailed workflow guides +- Complex multi-step processes +- Information too lengthy for main SKILL.md +- Content that's only needed for specific use cases + +## Structure Suggestions + +### API Reference Example +- Overview +- Authentication +- Endpoints with examples +- Error codes +- Rate limits + +### Workflow Guide Example +- Prerequisites +- Step-by-step instructions +- Common patterns +- Troubleshooting +- Best practices +""" + +EXAMPLE_ASSET = """# Example Asset File + +This placeholder represents where asset files would be stored. +Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed. + +Asset files are NOT intended to be loaded into context, but rather used within +the output Claude produces. + +Example asset files from other skills: +- Brand guidelines: logo.png, slides_template.pptx +- Frontend builder: hello-world/ directory with HTML/React boilerplate +- Typography: custom-font.ttf, font-family.woff2 +- Data: sample_data.csv, test_dataset.json + +## Common Asset Types + +- Templates: .pptx, .docx, boilerplate directories +- Images: .png, .jpg, .svg, .gif +- Fonts: .ttf, .otf, .woff, .woff2 +- Boilerplate code: Project directories, starter files +- Icons: .ico, .svg +- Data files: .csv, .json, .xml, .yaml + +Note: This is a text placeholder. Actual assets can be any file type. +""" + + +def title_case_skill_name(skill_name): + """Convert hyphenated skill name to Title Case for display.""" + return ' '.join(word.capitalize() for word in skill_name.split('-')) + + +def init_skill(skill_name, path): + """ + Initialize a new skill directory with template SKILL.md. + + Args: + skill_name: Name of the skill + path: Path where the skill directory should be created + + Returns: + Path to created skill directory, or None if error + """ + # Determine skill directory path + skill_dir = Path(path).resolve() / skill_name + + # Check if directory already exists + if skill_dir.exists(): + print(f"❌ Error: Skill directory already exists: {skill_dir}") + return None + + # Create skill directory + try: + skill_dir.mkdir(parents=True, exist_ok=False) + print(f"✅ Created skill directory: {skill_dir}") + except Exception as e: + print(f"❌ Error creating directory: {e}") + return None + + # Create SKILL.md from template + skill_title = title_case_skill_name(skill_name) + skill_content = SKILL_TEMPLATE.format( + skill_name=skill_name, + skill_title=skill_title + ) + + skill_md_path = skill_dir / 'SKILL.md' + try: + skill_md_path.write_text(skill_content) + print("✅ Created SKILL.md") + except Exception as e: + print(f"❌ Error creating SKILL.md: {e}") + return None + + # Create resource directories with example files + try: + # Create scripts/ directory with example script + scripts_dir = skill_dir / 'scripts' + scripts_dir.mkdir(exist_ok=True) + example_script = scripts_dir / 'example.py' + example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name)) + example_script.chmod(0o755) + print("✅ Created scripts/example.py") + + # Create references/ directory with example reference doc + references_dir = skill_dir / 'references' + references_dir.mkdir(exist_ok=True) + example_reference = references_dir / 'api_reference.md' + example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title)) + print("✅ Created references/api_reference.md") + + # Create assets/ directory with example asset placeholder + assets_dir = skill_dir / 'assets' + assets_dir.mkdir(exist_ok=True) + example_asset = assets_dir / 'example_asset.txt' + example_asset.write_text(EXAMPLE_ASSET) + print("✅ Created assets/example_asset.txt") + + # Create .openakita-i18n.json template for Chinese translation + i18n_data = { + "zh": { + "name": "[TODO: 中文技能名(2-6个字)]", + "description": "[TODO: 技能功能的中文描述]" + } + } + i18n_path = skill_dir / '.openakita-i18n.json' + i18n_path.write_text( + json.dumps(i18n_data, ensure_ascii=False, indent=2) + "\n" + ) + print("✅ Created .openakita-i18n.json (中文翻译模板)") + except Exception as e: + print(f"❌ Error creating resource directories: {e}") + return None + + # Print next steps + print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}") + print("\nNext steps:") + print("1. Edit SKILL.md to complete the TODO items and update the description") + print("2. Edit .openakita-i18n.json to fill in Chinese name and description") + print("3. Customize or delete the example files in scripts/, references/, and assets/") + print("4. Run the validator when ready to check the skill structure") + + return skill_dir + + +def main(): + if len(sys.argv) < 4 or sys.argv[2] != '--path': + print("Usage: init_skill.py --path ") + print("\nSkill name requirements:") + print(" - Kebab-case identifier (e.g., 'my-data-analyzer')") + print(" - Lowercase letters, digits, and hyphens only") + print(" - Max 64 characters") + print(" - Must match directory name exactly") + print("\nExamples:") + print(" init_skill.py my-new-skill --path skills/public") + print(" init_skill.py my-api-helper --path skills/private") + print(" init_skill.py custom-skill --path /custom/location") + sys.exit(1) + + skill_name = sys.argv[1] + path = sys.argv[3] + + print(f"🚀 Initializing skill: {skill_name}") + print(f" Location: {path}") + print() + + result = init_skill(skill_name, path) + + if result: + sys.exit(0) + else: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/skill-creator/scripts/package_skill.py b/account/admin/skills/skill-creator/scripts/package_skill.py new file mode 100644 index 0000000..5cd36cb --- /dev/null +++ b/account/admin/skills/skill-creator/scripts/package_skill.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +""" +Skill Packager - Creates a distributable .skill file of a skill folder + +Usage: + python utils/package_skill.py [output-directory] + +Example: + python utils/package_skill.py skills/public/my-skill + python utils/package_skill.py skills/public/my-skill ./dist +""" + +import sys +import zipfile +from pathlib import Path +from quick_validate import validate_skill + + +def package_skill(skill_path, output_dir=None): + """ + Package a skill folder into a .skill file. + + Args: + skill_path: Path to the skill folder + output_dir: Optional output directory for the .skill file (defaults to current directory) + + Returns: + Path to the created .skill file, or None if error + """ + skill_path = Path(skill_path).resolve() + + # Validate skill folder exists + if not skill_path.exists(): + print(f"❌ Error: Skill folder not found: {skill_path}") + return None + + if not skill_path.is_dir(): + print(f"❌ Error: Path is not a directory: {skill_path}") + return None + + # Validate SKILL.md exists + skill_md = skill_path / "SKILL.md" + if not skill_md.exists(): + print(f"❌ Error: SKILL.md not found in {skill_path}") + return None + + # Run validation before packaging + print("🔍 Validating skill...") + valid, message = validate_skill(skill_path) + if not valid: + print(f"❌ Validation failed: {message}") + print(" Please fix the validation errors before packaging.") + return None + print(f"✅ {message}\n") + + # Determine output location + skill_name = skill_path.name + if output_dir: + output_path = Path(output_dir).resolve() + output_path.mkdir(parents=True, exist_ok=True) + else: + output_path = Path.cwd() + + skill_filename = output_path / f"{skill_name}.skill" + + # Create the .skill file (zip format) + try: + with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: + # Walk through the skill directory + for file_path in skill_path.rglob('*'): + if file_path.is_file(): + # Calculate the relative path within the zip + arcname = file_path.relative_to(skill_path.parent) + zipf.write(file_path, arcname) + print(f" Added: {arcname}") + + print(f"\n✅ Successfully packaged skill to: {skill_filename}") + return skill_filename + + except Exception as e: + print(f"❌ Error creating .skill file: {e}") + return None + + +def main(): + if len(sys.argv) < 2: + print("Usage: python utils/package_skill.py [output-directory]") + print("\nExample:") + print(" python utils/package_skill.py skills/public/my-skill") + print(" python utils/package_skill.py skills/public/my-skill ./dist") + sys.exit(1) + + skill_path = sys.argv[1] + output_dir = sys.argv[2] if len(sys.argv) > 2 else None + + print(f"📦 Packaging skill: {skill_path}") + if output_dir: + print(f" Output directory: {output_dir}") + print() + + result = package_skill(skill_path, output_dir) + + if result: + sys.exit(0) + else: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/skill-creator/scripts/quick_validate.py b/account/admin/skills/skill-creator/scripts/quick_validate.py new file mode 100644 index 0000000..ed8e1dd --- /dev/null +++ b/account/admin/skills/skill-creator/scripts/quick_validate.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +""" +Quick validation script for skills - minimal version +""" + +import sys +import os +import re +import yaml +from pathlib import Path + +def validate_skill(skill_path): + """Basic validation of a skill""" + skill_path = Path(skill_path) + + # Check SKILL.md exists + skill_md = skill_path / 'SKILL.md' + if not skill_md.exists(): + return False, "SKILL.md not found" + + # Read and validate frontmatter + content = skill_md.read_text() + if not content.startswith('---'): + return False, "No YAML frontmatter found" + + # Extract frontmatter + match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL) + if not match: + return False, "Invalid frontmatter format" + + frontmatter_text = match.group(1) + + # Parse YAML frontmatter + try: + frontmatter = yaml.safe_load(frontmatter_text) + if not isinstance(frontmatter, dict): + return False, "Frontmatter must be a YAML dictionary" + except yaml.YAMLError as e: + return False, f"Invalid YAML in frontmatter: {e}" + + # Define allowed properties + ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata', 'compatibility'} + + # Check for unexpected properties (excluding nested keys under metadata) + unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES + if unexpected_keys: + return False, ( + f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. " + f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}" + ) + + # Check required fields + if 'name' not in frontmatter: + return False, "Missing 'name' in frontmatter" + if 'description' not in frontmatter: + return False, "Missing 'description' in frontmatter" + + # Extract name for validation + name = frontmatter.get('name', '') + if not isinstance(name, str): + return False, f"Name must be a string, got {type(name).__name__}" + name = name.strip() + if name: + # Check naming convention (kebab-case: lowercase with hyphens) + if not re.match(r'^[a-z0-9-]+$', name): + return False, f"Name '{name}' should be kebab-case (lowercase letters, digits, and hyphens only)" + if name.startswith('-') or name.endswith('-') or '--' in name: + return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens" + # Check name length (max 64 characters per spec) + if len(name) > 64: + return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters." + + # Extract and validate description + description = frontmatter.get('description', '') + if not isinstance(description, str): + return False, f"Description must be a string, got {type(description).__name__}" + description = description.strip() + if description: + # Check for angle brackets + if '<' in description or '>' in description: + return False, "Description cannot contain angle brackets (< or >)" + # Check description length (max 1024 characters per spec) + if len(description) > 1024: + return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters." + + # Validate compatibility field if present (optional) + compatibility = frontmatter.get('compatibility', '') + if compatibility: + if not isinstance(compatibility, str): + return False, f"Compatibility must be a string, got {type(compatibility).__name__}" + if len(compatibility) > 500: + return False, f"Compatibility is too long ({len(compatibility)} characters). Maximum is 500 characters." + + return True, "Skill is valid!" + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python quick_validate.py ") + sys.exit(1) + + valid, message = validate_skill(sys.argv[1]) + print(message) + sys.exit(0 if valid else 1) \ No newline at end of file diff --git a/account/admin/skills/slack-gif-creator/LICENSE.txt b/account/admin/skills/slack-gif-creator/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/slack-gif-creator/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/slack-gif-creator/SKILL.md b/account/admin/skills/slack-gif-creator/SKILL.md new file mode 100644 index 0000000..9379e62 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/SKILL.md @@ -0,0 +1,254 @@ +--- +name: openakita/skills@slack-gif-creator +description: Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like "make me a GIF of X doing Y for Slack." +license: Complete terms in LICENSE.txt +--- + +# Slack GIF Creator + +A toolkit providing utilities and knowledge for creating animated GIFs optimized for Slack. + +## Slack Requirements + +**Dimensions:** +- Emoji GIFs: 128x128 (recommended) +- Message GIFs: 480x480 + +**Parameters:** +- FPS: 10-30 (lower is smaller file size) +- Colors: 48-128 (fewer = smaller file size) +- Duration: Keep under 3 seconds for emoji GIFs + +## Core Workflow + +```python +from core.gif_builder import GIFBuilder +from PIL import Image, ImageDraw + +# 1. Create builder +builder = GIFBuilder(width=128, height=128, fps=10) + +# 2. Generate frames +for i in range(12): + frame = Image.new('RGB', (128, 128), (240, 248, 255)) + draw = ImageDraw.Draw(frame) + + # Draw your animation using PIL primitives + # (circles, polygons, lines, etc.) + + builder.add_frame(frame) + +# 3. Save with optimization +builder.save('output.gif', num_colors=48, optimize_for_emoji=True) +``` + +## Drawing Graphics + +### Working with User-Uploaded Images +If a user uploads an image, consider whether they want to: +- **Use it directly** (e.g., "animate this", "split this into frames") +- **Use it as inspiration** (e.g., "make something like this") + +Load and work with images using PIL: +```python +from PIL import Image + +uploaded = Image.open('file.png') +# Use directly, or just as reference for colors/style +``` + +### Drawing from Scratch +When drawing graphics from scratch, use PIL ImageDraw primitives: + +```python +from PIL import ImageDraw + +draw = ImageDraw.Draw(frame) + +# Circles/ovals +draw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3) + +# Stars, triangles, any polygon +points = [(x1, y1), (x2, y2), (x3, y3), ...] +draw.polygon(points, fill=(r, g, b), outline=(r, g, b), width=3) + +# Lines +draw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5) + +# Rectangles +draw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3) +``` + +**Don't use:** Emoji fonts (unreliable across platforms) or assume pre-packaged graphics exist in this skill. + +### Making Graphics Look Good + +Graphics should look polished and creative, not basic. Here's how: + +**Use thicker lines** - Always set `width=2` or higher for outlines and lines. Thin lines (width=1) look choppy and amateurish. + +**Add visual depth**: +- Use gradients for backgrounds (`create_gradient_background`) +- Layer multiple shapes for complexity (e.g., a star with a smaller star inside) + +**Make shapes more interesting**: +- Don't just draw a plain circle - add highlights, rings, or patterns +- Stars can have glows (draw larger, semi-transparent versions behind) +- Combine multiple shapes (stars + sparkles, circles + rings) + +**Pay attention to colors**: +- Use vibrant, complementary colors +- Add contrast (dark outlines on light shapes, light outlines on dark shapes) +- Consider the overall composition + +**For complex shapes** (hearts, snowflakes, etc.): +- Use combinations of polygons and ellipses +- Calculate points carefully for symmetry +- Add details (a heart can have a highlight curve, snowflakes have intricate branches) + +Be creative and detailed! A good Slack GIF should look polished, not like placeholder graphics. + +## Available Utilities + +### GIFBuilder (`core.gif_builder`) +Assembles frames and optimizes for Slack: +```python +builder = GIFBuilder(width=128, height=128, fps=10) +builder.add_frame(frame) # Add PIL Image +builder.add_frames(frames) # Add list of frames +builder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True) +``` + +### Validators (`core.validators`) +Check if GIF meets Slack requirements: +```python +from core.validators import validate_gif, is_slack_ready + +# Detailed validation +passes, info = validate_gif('my.gif', is_emoji=True, verbose=True) + +# Quick check +if is_slack_ready('my.gif'): + print("Ready!") +``` + +### Easing Functions (`core.easing`) +Smooth motion instead of linear: +```python +from core.easing import interpolate + +# Progress from 0.0 to 1.0 +t = i / (num_frames - 1) + +# Apply easing +y = interpolate(start=0, end=400, t=t, easing='ease_out') + +# Available: linear, ease_in, ease_out, ease_in_out, +# bounce_out, elastic_out, back_out +``` + +### Frame Helpers (`core.frame_composer`) +Convenience functions for common needs: +```python +from core.frame_composer import ( + create_blank_frame, # Solid color background + create_gradient_background, # Vertical gradient + draw_circle, # Helper for circles + draw_text, # Simple text rendering + draw_star # 5-pointed star +) +``` + +## Animation Concepts + +### Shake/Vibrate +Offset object position with oscillation: +- Use `math.sin()` or `math.cos()` with frame index +- Add small random variations for natural feel +- Apply to x and/or y position + +### Pulse/Heartbeat +Scale object size rhythmically: +- Use `math.sin(t * frequency * 2 * math.pi)` for smooth pulse +- For heartbeat: two quick pulses then pause (adjust sine wave) +- Scale between 0.8 and 1.2 of base size + +### Bounce +Object falls and bounces: +- Use `interpolate()` with `easing='bounce_out'` for landing +- Use `easing='ease_in'` for falling (accelerating) +- Apply gravity by increasing y velocity each frame + +### Spin/Rotate +Rotate object around center: +- PIL: `image.rotate(angle, resample=Image.BICUBIC)` +- For wobble: use sine wave for angle instead of linear + +### Fade In/Out +Gradually appear or disappear: +- Create RGBA image, adjust alpha channel +- Or use `Image.blend(image1, image2, alpha)` +- Fade in: alpha from 0 to 1 +- Fade out: alpha from 1 to 0 + +### Slide +Move object from off-screen to position: +- Start position: outside frame bounds +- End position: target location +- Use `interpolate()` with `easing='ease_out'` for smooth stop +- For overshoot: use `easing='back_out'` + +### Zoom +Scale and position for zoom effect: +- Zoom in: scale from 0.1 to 2.0, crop center +- Zoom out: scale from 2.0 to 1.0 +- Can add motion blur for drama (PIL filter) + +### Explode/Particle Burst +Create particles radiating outward: +- Generate particles with random angles and velocities +- Update each particle: `x += vx`, `y += vy` +- Add gravity: `vy += gravity_constant` +- Fade out particles over time (reduce alpha) + +## Optimization Strategies + +Only when asked to make the file size smaller, implement a few of the following methods: + +1. **Fewer frames** - Lower FPS (10 instead of 20) or shorter duration +2. **Fewer colors** - `num_colors=48` instead of 128 +3. **Smaller dimensions** - 128x128 instead of 480x480 +4. **Remove duplicates** - `remove_duplicates=True` in save() +5. **Emoji mode** - `optimize_for_emoji=True` auto-optimizes + +```python +# Maximum optimization for emoji +builder.save( + 'emoji.gif', + num_colors=48, + optimize_for_emoji=True, + remove_duplicates=True +) +``` + +## Philosophy + +This skill provides: +- **Knowledge**: Slack's requirements and animation concepts +- **Utilities**: GIFBuilder, validators, easing functions +- **Flexibility**: Create the animation logic using PIL primitives + +It does NOT provide: +- Rigid animation templates or pre-made functions +- Emoji font rendering (unreliable across platforms) +- A library of pre-packaged graphics built into the skill + +**Note on user uploads**: This skill doesn't include pre-built graphics, but if a user uploads an image, use PIL to load and work with it - interpret based on their request whether they want it used directly or just as inspiration. + +Be creative! Combine concepts (bouncing + rotating, pulsing + sliding, etc.) and use PIL's full capabilities. + +## Dependencies + +```bash +pip install pillow imageio numpy +``` diff --git a/account/admin/skills/slack-gif-creator/core/easing.py b/account/admin/skills/slack-gif-creator/core/easing.py new file mode 100644 index 0000000..772fa83 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/core/easing.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 +""" +Easing Functions - Timing functions for smooth animations. + +Provides various easing functions for natural motion and timing. +All functions take a value t (0.0 to 1.0) and return eased value (0.0 to 1.0). +""" + +import math + + +def linear(t: float) -> float: + """Linear interpolation (no easing).""" + return t + + +def ease_in_quad(t: float) -> float: + """Quadratic ease-in (slow start, accelerating).""" + return t * t + + +def ease_out_quad(t: float) -> float: + """Quadratic ease-out (fast start, decelerating).""" + return t * (2 - t) + + +def ease_in_out_quad(t: float) -> float: + """Quadratic ease-in-out (slow start and end).""" + if t < 0.5: + return 2 * t * t + return -1 + (4 - 2 * t) * t + + +def ease_in_cubic(t: float) -> float: + """Cubic ease-in (slow start).""" + return t * t * t + + +def ease_out_cubic(t: float) -> float: + """Cubic ease-out (fast start).""" + return (t - 1) * (t - 1) * (t - 1) + 1 + + +def ease_in_out_cubic(t: float) -> float: + """Cubic ease-in-out.""" + if t < 0.5: + return 4 * t * t * t + return (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 + + +def ease_in_bounce(t: float) -> float: + """Bounce ease-in (bouncy start).""" + return 1 - ease_out_bounce(1 - t) + + +def ease_out_bounce(t: float) -> float: + """Bounce ease-out (bouncy end).""" + if t < 1 / 2.75: + return 7.5625 * t * t + elif t < 2 / 2.75: + t -= 1.5 / 2.75 + return 7.5625 * t * t + 0.75 + elif t < 2.5 / 2.75: + t -= 2.25 / 2.75 + return 7.5625 * t * t + 0.9375 + else: + t -= 2.625 / 2.75 + return 7.5625 * t * t + 0.984375 + + +def ease_in_out_bounce(t: float) -> float: + """Bounce ease-in-out.""" + if t < 0.5: + return ease_in_bounce(t * 2) * 0.5 + return ease_out_bounce(t * 2 - 1) * 0.5 + 0.5 + + +def ease_in_elastic(t: float) -> float: + """Elastic ease-in (spring effect).""" + if t == 0 or t == 1: + return t + return -math.pow(2, 10 * (t - 1)) * math.sin((t - 1.1) * 5 * math.pi) + + +def ease_out_elastic(t: float) -> float: + """Elastic ease-out (spring effect).""" + if t == 0 or t == 1: + return t + return math.pow(2, -10 * t) * math.sin((t - 0.1) * 5 * math.pi) + 1 + + +def ease_in_out_elastic(t: float) -> float: + """Elastic ease-in-out.""" + if t == 0 or t == 1: + return t + t = t * 2 - 1 + if t < 0: + return -0.5 * math.pow(2, 10 * t) * math.sin((t - 0.1) * 5 * math.pi) + return math.pow(2, -10 * t) * math.sin((t - 0.1) * 5 * math.pi) * 0.5 + 1 + + +# Convenience mapping +EASING_FUNCTIONS = { + "linear": linear, + "ease_in": ease_in_quad, + "ease_out": ease_out_quad, + "ease_in_out": ease_in_out_quad, + "bounce_in": ease_in_bounce, + "bounce_out": ease_out_bounce, + "bounce": ease_in_out_bounce, + "elastic_in": ease_in_elastic, + "elastic_out": ease_out_elastic, + "elastic": ease_in_out_elastic, +} + + +def get_easing(name: str = "linear"): + """Get easing function by name.""" + return EASING_FUNCTIONS.get(name, linear) + + +def interpolate(start: float, end: float, t: float, easing: str = "linear") -> float: + """ + Interpolate between two values with easing. + + Args: + start: Start value + end: End value + t: Progress from 0.0 to 1.0 + easing: Name of easing function + + Returns: + Interpolated value + """ + ease_func = get_easing(easing) + eased_t = ease_func(t) + return start + (end - start) * eased_t + + +def ease_back_in(t: float) -> float: + """Back ease-in (slight overshoot backward before forward motion).""" + c1 = 1.70158 + c3 = c1 + 1 + return c3 * t * t * t - c1 * t * t + + +def ease_back_out(t: float) -> float: + """Back ease-out (overshoot forward then settle back).""" + c1 = 1.70158 + c3 = c1 + 1 + return 1 + c3 * pow(t - 1, 3) + c1 * pow(t - 1, 2) + + +def ease_back_in_out(t: float) -> float: + """Back ease-in-out (overshoot at both ends).""" + c1 = 1.70158 + c2 = c1 * 1.525 + if t < 0.5: + return (pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2 + return (pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2 + + +def apply_squash_stretch( + base_scale: tuple[float, float], intensity: float, direction: str = "vertical" +) -> tuple[float, float]: + """ + Calculate squash and stretch scales for more dynamic animation. + + Args: + base_scale: (width_scale, height_scale) base scales + intensity: Squash/stretch intensity (0.0-1.0) + direction: 'vertical', 'horizontal', or 'both' + + Returns: + (width_scale, height_scale) with squash/stretch applied + """ + width_scale, height_scale = base_scale + + if direction == "vertical": + # Compress vertically, expand horizontally (preserve volume) + height_scale *= 1 - intensity * 0.5 + width_scale *= 1 + intensity * 0.5 + elif direction == "horizontal": + # Compress horizontally, expand vertically + width_scale *= 1 - intensity * 0.5 + height_scale *= 1 + intensity * 0.5 + elif direction == "both": + # General squash (both dimensions) + width_scale *= 1 - intensity * 0.3 + height_scale *= 1 - intensity * 0.3 + + return (width_scale, height_scale) + + +def calculate_arc_motion( + start: tuple[float, float], end: tuple[float, float], height: float, t: float +) -> tuple[float, float]: + """ + Calculate position along a parabolic arc (natural motion path). + + Args: + start: (x, y) starting position + end: (x, y) ending position + height: Arc height at midpoint (positive = upward) + t: Progress (0.0-1.0) + + Returns: + (x, y) position along arc + """ + x1, y1 = start + x2, y2 = end + + # Linear interpolation for x + x = x1 + (x2 - x1) * t + + # Parabolic interpolation for y + # y = start + progress * (end - start) + arc_offset + # Arc offset peaks at t=0.5 + arc_offset = 4 * height * t * (1 - t) + y = y1 + (y2 - y1) * t - arc_offset + + return (x, y) + + +# Add new easing functions to the convenience mapping +EASING_FUNCTIONS.update( + { + "back_in": ease_back_in, + "back_out": ease_back_out, + "back_in_out": ease_back_in_out, + "anticipate": ease_back_in, # Alias + "overshoot": ease_back_out, # Alias + } +) diff --git a/account/admin/skills/slack-gif-creator/core/frame_composer.py b/account/admin/skills/slack-gif-creator/core/frame_composer.py new file mode 100644 index 0000000..1afe434 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/core/frame_composer.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +""" +Frame Composer - Utilities for composing visual elements into frames. + +Provides functions for drawing shapes, text, emojis, and compositing elements +together to create animation frames. +""" + +from typing import Optional + +import numpy as np +from PIL import Image, ImageDraw, ImageFont + + +def create_blank_frame( + width: int, height: int, color: tuple[int, int, int] = (255, 255, 255) +) -> Image.Image: + """ + Create a blank frame with solid color background. + + Args: + width: Frame width + height: Frame height + color: RGB color tuple (default: white) + + Returns: + PIL Image + """ + return Image.new("RGB", (width, height), color) + + +def draw_circle( + frame: Image.Image, + center: tuple[int, int], + radius: int, + fill_color: Optional[tuple[int, int, int]] = None, + outline_color: Optional[tuple[int, int, int]] = None, + outline_width: int = 1, +) -> Image.Image: + """ + Draw a circle on a frame. + + Args: + frame: PIL Image to draw on + center: (x, y) center position + radius: Circle radius + fill_color: RGB fill color (None for no fill) + outline_color: RGB outline color (None for no outline) + outline_width: Outline width in pixels + + Returns: + Modified frame + """ + draw = ImageDraw.Draw(frame) + x, y = center + bbox = [x - radius, y - radius, x + radius, y + radius] + draw.ellipse(bbox, fill=fill_color, outline=outline_color, width=outline_width) + return frame + + +def draw_text( + frame: Image.Image, + text: str, + position: tuple[int, int], + color: tuple[int, int, int] = (0, 0, 0), + centered: bool = False, +) -> Image.Image: + """ + Draw text on a frame. + + Args: + frame: PIL Image to draw on + text: Text to draw + position: (x, y) position (top-left unless centered=True) + color: RGB text color + centered: If True, center text at position + + Returns: + Modified frame + """ + draw = ImageDraw.Draw(frame) + + # Uses Pillow's default font. + # If the font should be changed for the emoji, add additional logic here. + font = ImageFont.load_default() + + if centered: + bbox = draw.textbbox((0, 0), text, font=font) + text_width = bbox[2] - bbox[0] + text_height = bbox[3] - bbox[1] + x = position[0] - text_width // 2 + y = position[1] - text_height // 2 + position = (x, y) + + draw.text(position, text, fill=color, font=font) + return frame + + +def create_gradient_background( + width: int, + height: int, + top_color: tuple[int, int, int], + bottom_color: tuple[int, int, int], +) -> Image.Image: + """ + Create a vertical gradient background. + + Args: + width: Frame width + height: Frame height + top_color: RGB color at top + bottom_color: RGB color at bottom + + Returns: + PIL Image with gradient + """ + frame = Image.new("RGB", (width, height)) + draw = ImageDraw.Draw(frame) + + # Calculate color step for each row + r1, g1, b1 = top_color + r2, g2, b2 = bottom_color + + for y in range(height): + # Interpolate color + ratio = y / height + r = int(r1 * (1 - ratio) + r2 * ratio) + g = int(g1 * (1 - ratio) + g2 * ratio) + b = int(b1 * (1 - ratio) + b2 * ratio) + + # Draw horizontal line + draw.line([(0, y), (width, y)], fill=(r, g, b)) + + return frame + + +def draw_star( + frame: Image.Image, + center: tuple[int, int], + size: int, + fill_color: tuple[int, int, int], + outline_color: Optional[tuple[int, int, int]] = None, + outline_width: int = 1, +) -> Image.Image: + """ + Draw a 5-pointed star. + + Args: + frame: PIL Image to draw on + center: (x, y) center position + size: Star size (outer radius) + fill_color: RGB fill color + outline_color: RGB outline color (None for no outline) + outline_width: Outline width + + Returns: + Modified frame + """ + import math + + draw = ImageDraw.Draw(frame) + x, y = center + + # Calculate star points + points = [] + for i in range(10): + angle = (i * 36 - 90) * math.pi / 180 # 36 degrees per point, start at top + radius = size if i % 2 == 0 else size * 0.4 # Alternate between outer and inner + px = x + radius * math.cos(angle) + py = y + radius * math.sin(angle) + points.append((px, py)) + + # Draw star + draw.polygon(points, fill=fill_color, outline=outline_color, width=outline_width) + + return frame diff --git a/account/admin/skills/slack-gif-creator/core/gif_builder.py b/account/admin/skills/slack-gif-creator/core/gif_builder.py new file mode 100644 index 0000000..5759f14 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/core/gif_builder.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python3 +""" +GIF Builder - Core module for assembling frames into GIFs optimized for Slack. + +This module provides the main interface for creating GIFs from programmatically +generated frames, with automatic optimization for Slack's requirements. +""" + +from pathlib import Path +from typing import Optional + +import imageio.v3 as imageio +import numpy as np +from PIL import Image + + +class GIFBuilder: + """Builder for creating optimized GIFs from frames.""" + + def __init__(self, width: int = 480, height: int = 480, fps: int = 15): + """ + Initialize GIF builder. + + Args: + width: Frame width in pixels + height: Frame height in pixels + fps: Frames per second + """ + self.width = width + self.height = height + self.fps = fps + self.frames: list[np.ndarray] = [] + + def add_frame(self, frame: np.ndarray | Image.Image): + """ + Add a frame to the GIF. + + Args: + frame: Frame as numpy array or PIL Image (will be converted to RGB) + """ + if isinstance(frame, Image.Image): + frame = np.array(frame.convert("RGB")) + + # Ensure frame is correct size + if frame.shape[:2] != (self.height, self.width): + pil_frame = Image.fromarray(frame) + pil_frame = pil_frame.resize( + (self.width, self.height), Image.Resampling.LANCZOS + ) + frame = np.array(pil_frame) + + self.frames.append(frame) + + def add_frames(self, frames: list[np.ndarray | Image.Image]): + """Add multiple frames at once.""" + for frame in frames: + self.add_frame(frame) + + def optimize_colors( + self, num_colors: int = 128, use_global_palette: bool = True + ) -> list[np.ndarray]: + """ + Reduce colors in all frames using quantization. + + Args: + num_colors: Target number of colors (8-256) + use_global_palette: Use a single palette for all frames (better compression) + + Returns: + List of color-optimized frames + """ + optimized = [] + + if use_global_palette and len(self.frames) > 1: + # Create a global palette from all frames + # Sample frames to build palette + sample_size = min(5, len(self.frames)) + sample_indices = [ + int(i * len(self.frames) / sample_size) for i in range(sample_size) + ] + sample_frames = [self.frames[i] for i in sample_indices] + + # Combine sample frames into a single image for palette generation + # Flatten each frame to get all pixels, then stack them + all_pixels = np.vstack( + [f.reshape(-1, 3) for f in sample_frames] + ) # (total_pixels, 3) + + # Create a properly-shaped RGB image from the pixel data + # We'll make a roughly square image from all the pixels + total_pixels = len(all_pixels) + width = min(512, int(np.sqrt(total_pixels))) # Reasonable width, max 512 + height = (total_pixels + width - 1) // width # Ceiling division + + # Pad if necessary to fill the rectangle + pixels_needed = width * height + if pixels_needed > total_pixels: + padding = np.zeros((pixels_needed - total_pixels, 3), dtype=np.uint8) + all_pixels = np.vstack([all_pixels, padding]) + + # Reshape to proper RGB image format (H, W, 3) + img_array = ( + all_pixels[:pixels_needed].reshape(height, width, 3).astype(np.uint8) + ) + combined_img = Image.fromarray(img_array, mode="RGB") + + # Generate global palette + global_palette = combined_img.quantize(colors=num_colors, method=2) + + # Apply global palette to all frames + for frame in self.frames: + pil_frame = Image.fromarray(frame) + quantized = pil_frame.quantize(palette=global_palette, dither=1) + optimized.append(np.array(quantized.convert("RGB"))) + else: + # Use per-frame quantization + for frame in self.frames: + pil_frame = Image.fromarray(frame) + quantized = pil_frame.quantize(colors=num_colors, method=2, dither=1) + optimized.append(np.array(quantized.convert("RGB"))) + + return optimized + + def deduplicate_frames(self, threshold: float = 0.9995) -> int: + """ + Remove duplicate or near-duplicate consecutive frames. + + Args: + threshold: Similarity threshold (0.0-1.0). Higher = more strict (0.9995 = nearly identical). + Use 0.9995+ to preserve subtle animations, 0.98 for aggressive removal. + + Returns: + Number of frames removed + """ + if len(self.frames) < 2: + return 0 + + deduplicated = [self.frames[0]] + removed_count = 0 + + for i in range(1, len(self.frames)): + # Compare with previous frame + prev_frame = np.array(deduplicated[-1], dtype=np.float32) + curr_frame = np.array(self.frames[i], dtype=np.float32) + + # Calculate similarity (normalized) + diff = np.abs(prev_frame - curr_frame) + similarity = 1.0 - (np.mean(diff) / 255.0) + + # Keep frame if sufficiently different + # High threshold (0.9995+) means only remove nearly identical frames + if similarity < threshold: + deduplicated.append(self.frames[i]) + else: + removed_count += 1 + + self.frames = deduplicated + return removed_count + + def save( + self, + output_path: str | Path, + num_colors: int = 128, + optimize_for_emoji: bool = False, + remove_duplicates: bool = False, + ) -> dict: + """ + Save frames as optimized GIF for Slack. + + Args: + output_path: Where to save the GIF + num_colors: Number of colors to use (fewer = smaller file) + optimize_for_emoji: If True, optimize for emoji size (128x128, fewer colors) + remove_duplicates: If True, remove duplicate consecutive frames (opt-in) + + Returns: + Dictionary with file info (path, size, dimensions, frame_count) + """ + if not self.frames: + raise ValueError("No frames to save. Add frames with add_frame() first.") + + output_path = Path(output_path) + + # Remove duplicate frames to reduce file size + if remove_duplicates: + removed = self.deduplicate_frames(threshold=0.9995) + if removed > 0: + print( + f" Removed {removed} nearly identical frames (preserved subtle animations)" + ) + + # Optimize for emoji if requested + if optimize_for_emoji: + if self.width > 128 or self.height > 128: + print( + f" Resizing from {self.width}x{self.height} to 128x128 for emoji" + ) + self.width = 128 + self.height = 128 + # Resize all frames + resized_frames = [] + for frame in self.frames: + pil_frame = Image.fromarray(frame) + pil_frame = pil_frame.resize((128, 128), Image.Resampling.LANCZOS) + resized_frames.append(np.array(pil_frame)) + self.frames = resized_frames + num_colors = min(num_colors, 48) # More aggressive color limit for emoji + + # More aggressive FPS reduction for emoji + if len(self.frames) > 12: + print( + f" Reducing frames from {len(self.frames)} to ~12 for emoji size" + ) + # Keep every nth frame to get close to 12 frames + keep_every = max(1, len(self.frames) // 12) + self.frames = [ + self.frames[i] for i in range(0, len(self.frames), keep_every) + ] + + # Optimize colors with global palette + optimized_frames = self.optimize_colors(num_colors, use_global_palette=True) + + # Calculate frame duration in milliseconds + frame_duration = 1000 / self.fps + + # Save GIF + imageio.imwrite( + output_path, + optimized_frames, + duration=frame_duration, + loop=0, # Infinite loop + ) + + # Get file info + file_size_kb = output_path.stat().st_size / 1024 + file_size_mb = file_size_kb / 1024 + + info = { + "path": str(output_path), + "size_kb": file_size_kb, + "size_mb": file_size_mb, + "dimensions": f"{self.width}x{self.height}", + "frame_count": len(optimized_frames), + "fps": self.fps, + "duration_seconds": len(optimized_frames) / self.fps, + "colors": num_colors, + } + + # Print info + print(f"\n✓ GIF created successfully!") + print(f" Path: {output_path}") + print(f" Size: {file_size_kb:.1f} KB ({file_size_mb:.2f} MB)") + print(f" Dimensions: {self.width}x{self.height}") + print(f" Frames: {len(optimized_frames)} @ {self.fps} fps") + print(f" Duration: {info['duration_seconds']:.1f}s") + print(f" Colors: {num_colors}") + + # Size info + if optimize_for_emoji: + print(f" Optimized for emoji (128x128, reduced colors)") + if file_size_mb > 1.0: + print(f"\n Note: Large file size ({file_size_kb:.1f} KB)") + print(" Consider: fewer frames, smaller dimensions, or fewer colors") + + return info + + def clear(self): + """Clear all frames (useful for creating multiple GIFs).""" + self.frames = [] diff --git a/account/admin/skills/slack-gif-creator/core/validators.py b/account/admin/skills/slack-gif-creator/core/validators.py new file mode 100644 index 0000000..1dc0bc1 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/core/validators.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +""" +Validators - Check if GIFs meet Slack's requirements. + +These validators help ensure your GIFs meet Slack's size and dimension constraints. +""" + +from pathlib import Path + + +def validate_gif( + gif_path: str | Path, is_emoji: bool = True, verbose: bool = True +) -> tuple[bool, dict]: + """ + Validate GIF for Slack (dimensions, size, frame count). + + Args: + gif_path: Path to GIF file + is_emoji: True for emoji (128x128 recommended), False for message GIF + verbose: Print validation details + + Returns: + Tuple of (passes: bool, results: dict with all details) + """ + from PIL import Image + + gif_path = Path(gif_path) + + if not gif_path.exists(): + return False, {"error": f"File not found: {gif_path}"} + + # Get file size + size_bytes = gif_path.stat().st_size + size_kb = size_bytes / 1024 + size_mb = size_kb / 1024 + + # Get dimensions and frame info + try: + with Image.open(gif_path) as img: + width, height = img.size + + # Count frames + frame_count = 0 + try: + while True: + img.seek(frame_count) + frame_count += 1 + except EOFError: + pass + + # Get duration + try: + duration_ms = img.info.get("duration", 100) + total_duration = (duration_ms * frame_count) / 1000 + fps = frame_count / total_duration if total_duration > 0 else 0 + except Exception: + total_duration = None + fps = None + + except Exception as e: + return False, {"error": f"Failed to read GIF: {e}"} + + # Validate dimensions + if is_emoji: + optimal = width == height == 128 + acceptable = width == height and 64 <= width <= 128 + dim_pass = acceptable + else: + aspect_ratio = ( + max(width, height) / min(width, height) + if min(width, height) > 0 + else float("inf") + ) + dim_pass = aspect_ratio <= 2.0 and 320 <= min(width, height) <= 640 + + results = { + "file": str(gif_path), + "passes": dim_pass, + "width": width, + "height": height, + "size_kb": size_kb, + "size_mb": size_mb, + "frame_count": frame_count, + "duration_seconds": total_duration, + "fps": fps, + "is_emoji": is_emoji, + "optimal": optimal if is_emoji else None, + } + + # Print if verbose + if verbose: + print(f"\nValidating {gif_path.name}:") + print( + f" Dimensions: {width}x{height}" + + ( + f" ({'optimal' if optimal else 'acceptable'})" + if is_emoji and acceptable + else "" + ) + ) + print( + f" Size: {size_kb:.1f} KB" + + (f" ({size_mb:.2f} MB)" if size_mb >= 1.0 else "") + ) + print( + f" Frames: {frame_count}" + + (f" @ {fps:.1f} fps ({total_duration:.1f}s)" if fps else "") + ) + + if not dim_pass: + print( + f" Note: {'Emoji should be 128x128' if is_emoji else 'Unusual dimensions for Slack'}" + ) + + if size_mb > 5.0: + print(f" Note: Large file size - consider fewer frames/colors") + + return dim_pass, results + + +def is_slack_ready( + gif_path: str | Path, is_emoji: bool = True, verbose: bool = True +) -> bool: + """ + Quick check if GIF is ready for Slack. + + Args: + gif_path: Path to GIF file + is_emoji: True for emoji GIF, False for message GIF + verbose: Print feedback + + Returns: + True if dimensions are acceptable + """ + passes, _ = validate_gif(gif_path, is_emoji, verbose) + return passes diff --git a/account/admin/skills/slack-gif-creator/requirements.txt b/account/admin/skills/slack-gif-creator/requirements.txt new file mode 100644 index 0000000..8bc4493 --- /dev/null +++ b/account/admin/skills/slack-gif-creator/requirements.txt @@ -0,0 +1,4 @@ +pillow>=10.0.0 +imageio>=2.31.0 +imageio-ffmpeg>=0.4.9 +numpy>=1.24.0 \ No newline at end of file diff --git a/account/admin/skills/summarizer/.openakita-i18n.json b/account/admin/skills/summarizer/.openakita-i18n.json new file mode 100644 index 0000000..48dcfb4 --- /dev/null +++ b/account/admin/skills/summarizer/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "通用内容摘要", + "description": "从任意来源(网页、本地文件、YouTube 视频、原始文本)提取并生成摘要,支持多种输出格式(要点、执行摘要、详细笔记)和可配置的摘要长度与风格。" + } +} diff --git a/account/admin/skills/summarizer/SKILL.md b/account/admin/skills/summarizer/SKILL.md new file mode 100644 index 0000000..3c6a315 --- /dev/null +++ b/account/admin/skills/summarizer/SKILL.md @@ -0,0 +1,617 @@ +--- +name: openakita/skills@summarizer +description: Summarize content from any source — URLs, local files, YouTube videos, and raw text. Use when the user asks to summarize a webpage, PDF, document, article, video, or any content. Supports multiple output formats (bullet points, executive summary, detailed notes) and configurable length. Can also extract raw content without summarization. +license: MIT +metadata: + author: openakita + version: "1.0.0" + based_on: moltbot/moltbot/summarize +--- + +# Universal Content Summarizer + +Summarize content from any source: URLs, local files, YouTube videos, clipboard text, and more. Flexible output formats with configurable depth and style. + +## When to Use This Skill + +- User says "summarize this" and provides a URL, file, or text +- User shares a link to a webpage/article and wants a quick overview +- User has a PDF or document they want condensed +- User wants to extract content from a URL without summarizing (extract-only mode) +- User needs different summary formats for different audiences (executive vs. technical) +- User wants to summarize multiple sources and combine insights +- User asks for a TL;DR of any content + +## Prerequisites + +### Core Dependencies + +No mandatory external dependencies for basic text summarization — the AI model handles it directly. + +### For URL Content Extraction + +The agent should use available web browsing/fetching tools to retrieve URL content. If running in an environment with shell access: + +```bash +# For advanced HTML parsing (optional) +pip install beautifulsoup4 requests + +# For PDF text extraction (optional) +pip install PyPDF2 +# or +pip install pdfplumber +``` + +### For YouTube Videos + +If the content source is a YouTube URL, this skill delegates to the youtube-summarizer or bilibili-watcher skills if available. Otherwise, it uses: + +```bash +pip install youtube-transcript-api +``` + +### Supported Input Types + +| Input Type | How to Provide | Notes | +|---|---|---| +| URL (webpage) | Paste the URL | HTML content extracted automatically | +| URL (YouTube) | Paste YouTube link | Transcript extracted via API | +| Local file (text) | File path | `.txt`, `.md`, `.rst`, `.csv` | +| Local file (PDF) | File path | Requires PyPDF2 or pdfplumber | +| Local file (HTML) | File path | Parsed with BeautifulSoup | +| Local file (DOCX) | File path | Requires python-docx | +| Raw text | Paste directly | Any length | +| Clipboard | "Summarize my clipboard" | If clipboard access available | + +--- + +## Instructions + +### Step 1: Identify the Content Source + +Determine what the user wants summarized and how to access it: + +``` +Input Analysis: +1. Is it a URL? → Fetch the content +2. Is it a file path? → Read the file +3. Is it raw text? → Use directly +4. Is it a YouTube link? → Extract transcript +5. Is it multiple sources? → Process each, then combine +``` + +**URL Detection Patterns:** + +```python +import re + +def classify_input(text: str) -> str: + """Classify the input type.""" + text = text.strip() + + # YouTube URLs + youtube_pattern = r'(youtube\.com|youtu\.be|youtube\.com/shorts)' + if re.search(youtube_pattern, text): + return 'youtube' + + # Bilibili URLs + if 'bilibili.com' in text or 'b23.tv' in text: + return 'bilibili' + + # General URLs + if re.match(r'https?://', text): + return 'url' + + # File paths + if any(text.endswith(ext) for ext in ['.pdf', '.txt', '.md', '.html', '.docx', '.rst', '.csv']): + return 'file' + + # Raw text + return 'text' +``` + +### Step 2: Extract Content + +#### From URLs (Webpages) + +Use the available web fetching tools to retrieve and parse HTML content. Extract the main article text, removing navigation, ads, footers, and other boilerplate. + +**Key extraction goals:** +- Article title and author +- Publication date if available +- Main body text with structure preserved +- Images and captions (noted but not downloaded) +- Any embedded data tables + +```python +from bs4 import BeautifulSoup +import requests + +def extract_url_content(url: str) -> dict: + """Extract main content from a URL.""" + response = requests.get(url, headers={ + 'User-Agent': 'Mozilla/5.0 (compatible; ContentSummarizer/1.0)' + }, timeout=30) + response.raise_for_status() + + soup = BeautifulSoup(response.text, 'html.parser') + + # Remove script, style, nav, footer elements + for tag in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']): + tag.decompose() + + # Try to find the main article content + article = soup.find('article') or soup.find('main') or soup.find('body') + + title = soup.find('title') + title_text = title.get_text().strip() if title else 'Untitled' + + return { + 'title': title_text, + 'text': article.get_text(separator='\n', strip=True) if article else '', + 'url': url + } +``` + +#### From Local Files + +```python +from pathlib import Path + +def extract_file_content(filepath: str) -> dict: + """Extract text from various file formats.""" + path = Path(filepath) + suffix = path.suffix.lower() + + if suffix in ('.txt', '.md', '.rst', '.csv'): + text = path.read_text(encoding='utf-8') + return {'title': path.name, 'text': text, 'format': suffix} + + elif suffix == '.pdf': + return extract_pdf(filepath) + + elif suffix == '.html': + text = path.read_text(encoding='utf-8') + soup = BeautifulSoup(text, 'html.parser') + for tag in soup(['script', 'style']): + tag.decompose() + return { + 'title': path.name, + 'text': soup.get_text(separator='\n', strip=True), + 'format': 'html' + } + + elif suffix == '.docx': + return extract_docx(filepath) + + else: + # Try reading as plain text + try: + text = path.read_text(encoding='utf-8') + return {'title': path.name, 'text': text, 'format': 'unknown'} + except UnicodeDecodeError: + raise ValueError(f"Cannot read binary file: {filepath}") + + +def extract_pdf(filepath: str) -> dict: + """Extract text from PDF using available libraries.""" + try: + import pdfplumber + with pdfplumber.open(filepath) as pdf: + pages = [page.extract_text() or '' for page in pdf.pages] + return { + 'title': Path(filepath).name, + 'text': '\n\n'.join(pages), + 'format': 'pdf', + 'pages': len(pdf.pages) + } + except ImportError: + pass + + try: + from PyPDF2 import PdfReader + reader = PdfReader(filepath) + pages = [page.extract_text() or '' for page in reader.pages] + return { + 'title': Path(filepath).name, + 'text': '\n\n'.join(pages), + 'format': 'pdf', + 'pages': len(reader.pages) + } + except ImportError: + raise RuntimeError("Install pdfplumber or PyPDF2 to read PDFs: pip install pdfplumber") + + +def extract_docx(filepath: str) -> dict: + """Extract text from DOCX files.""" + try: + from docx import Document + doc = Document(filepath) + paragraphs = [p.text for p in doc.paragraphs if p.text.strip()] + return { + 'title': Path(filepath).name, + 'text': '\n\n'.join(paragraphs), + 'format': 'docx' + } + except ImportError: + raise RuntimeError("Install python-docx to read DOCX files: pip install python-docx") +``` + +#### From YouTube Videos + +Delegate to the youtube-summarizer skill or use youtube-transcript-api directly: + +```python +from youtube_transcript_api import YouTubeTranscriptApi + +def extract_youtube_content(url: str) -> dict: + """Extract transcript from YouTube video.""" + video_id = extract_video_id(url) # See youtube-summarizer skill + transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en', 'zh-Hans', 'ja']) + text = ' '.join(entry['text'] for entry in transcript) + return { + 'title': f'YouTube Video {video_id}', + 'text': text, + 'format': 'youtube', + 'segments': transcript + } +``` + +### Step 3: Generate the Summary + +Choose the output format based on user request or default to bullet points. + +--- + +## Output Formats + +### Format 1: Bullet Points (Default) + +Best for: Quick scanning, team sharing, Slack/email updates. + +``` +# Summary: [Title] + +**Source**: [URL or filename] +**Length**: ~X words / X pages / X minutes + +## Key Points +• [Most important finding/conclusion] +• [Second key point] +• [Third key point] +• [Fourth key point — include specific numbers/data if available] +• [Fifth key point] + +## Notable Details +• [Interesting data point or quote] +• [Counter-argument or limitation mentioned] +``` + +**Prompt template:** +``` +Summarize the following content into 5-8 bullet points. Each bullet should: +- Be self-contained (understandable without reading the full text) +- Include specific numbers, names, or dates when relevant +- Be ordered by importance (most important first) +- Be concise (1-2 sentences max) + +Content: +{content} +``` + +### Format 2: Executive Summary + +Best for: Leadership updates, decision-making, meeting prep. + +``` +# Executive Summary: [Title] + +**Source**: [URL/file] | **Date**: [if available] | **Read time**: ~X min + +## Bottom Line +[1-2 sentences: the single most important takeaway] + +## Context +[2-3 sentences: why this matters, background] + +## Key Findings +1. [Finding with supporting data] +2. [Finding with supporting data] +3. [Finding with supporting data] + +## Implications +[What this means for the reader/team/organization] + +## Recommended Actions +1. [Action item] +2. [Action item] +``` + +**Prompt template:** +``` +Write an executive summary of the following content. Target audience: busy decision-makers +who need to understand the core message in under 2 minutes. + +Structure: +1. Bottom Line (1-2 sentences — what's the one thing they need to know?) +2. Context (2-3 sentences — why does this matter?) +3. Key Findings (3-5 numbered points with data) +4. Implications (what this means going forward) +5. Recommended Actions (concrete next steps) + +Content: +{content} +``` + +### Format 3: Detailed Notes + +Best for: Research, studying, reference material. + +``` +# Detailed Notes: [Title] + +**Source**: [URL/file] +**Summary date**: [today] +**Original length**: ~X words + +## Overview +[3-5 sentence comprehensive overview] + +## Section 1: [Topic] +[Detailed notes preserving key information, quotes, data] +- Sub-point with specifics +- Sub-point with specifics + +## Section 2: [Topic] +[Detailed notes] + +## Section 3: [Topic] +[Detailed notes] + +## Key Quotes +> "[Exact quote]" — [Source/Author] +> "[Exact quote]" — [Source/Author] + +## Data & Statistics +| Metric | Value | Context | +|---|---|---| +| [metric] | [value] | [context] | + +## References & Links +- [Reference mentioned in the content] +``` + +### Format 4: Extract Only (No Summarization) + +Best for: Content extraction for downstream processing. + +When the user says "just extract" or "don't summarize", return the raw extracted text in clean markdown format without any summarization or analysis: + +``` +# Extracted Content: [Title] + +**Source**: [URL/file] +**Extracted**: [timestamp] +**Word count**: X + +--- + +[Full extracted text in clean markdown] +``` + +--- + +## Workflows + +### Workflow 1: Quick URL Summary + +User says: "Summarize https://example.com/article" + +1. Detect input type: URL +2. Fetch and parse the webpage content +3. Generate bullet-point summary (default format) +4. Present with source attribution + +### Workflow 2: PDF Summary + +User says: "Summarize this PDF: /path/to/document.pdf" + +1. Detect input type: file (PDF) +2. Extract text from all pages +3. Note total page count +4. Generate summary in requested format +5. Flag any extraction issues (scanned PDFs, images, etc.) + +### Workflow 3: Custom Format Summary + +User says: "Give me an executive summary of this article" + +1. Detect input type and extract content +2. Use executive summary format +3. Include bottom line, key findings, and action items + +### Workflow 4: Multi-Source Synthesis + +User provides multiple URLs/files: + +1. Extract content from each source +2. Summarize each independently +3. Create a synthesis section highlighting: + - Common themes across sources + - Contradictions or differing perspectives + - Unique insights from each source +4. Present combined analysis + +### Workflow 5: Configurable Length + +User says: "Give me a 3-sentence summary" or "detailed 2000-word summary" + +1. Extract content +2. Adjust summary length based on user specification: + - "brief" / "TL;DR" → 2-3 sentences + - "short" → 5-8 bullet points + - "medium" (default) → Full structured summary + - "detailed" / "comprehensive" → Detailed notes format with all specifics + +### Workflow 6: Content Extraction Only + +User says: "Just extract the text from this URL, don't summarize" + +1. Fetch and parse the content +2. Clean up HTML/formatting artifacts +3. Return raw text in clean markdown +4. No summarization applied + +### Workflow 7: YouTube/Video Summary + +User shares a YouTube or Bilibili link: + +1. Detect as video URL +2. Extract transcript (delegate to youtube-summarizer or bilibili-watcher if available) +3. Summarize transcript with timestamps +4. Format output appropriate to video content + +--- + +## Configurable Options + +When processing a summarization request, consider these adjustable parameters: + +| Parameter | Options | Default | +|---|---|---| +| **Format** | bullet, executive, detailed, extract-only | bullet | +| **Length** | brief, short, medium, detailed | medium | +| **Language** | Output language code | Same as source | +| **Focus** | Specific topic/aspect to emphasize | None (general) | +| **Audience** | technical, general, executive, academic | general | +| **Include quotes** | yes/no | yes for detailed | +| **Include data** | yes/no | yes | +| **Max points** | Number of bullet points | 8 | + +Users can specify these naturally: +- "Summarize in Chinese" → language: zh +- "Technical summary for engineers" → audience: technical +- "Just the top 3 points" → max_points: 3, length: brief + +--- + +## Common Pitfalls + +### 1. Paywalled or Login-Required Content + +**Problem**: Many news sites and platforms require subscriptions or login. + +**Solutions**: +- Try the URL first; many sites allow limited free access +- Check for cached versions or alternative URLs +- Inform the user if content is inaccessible and suggest alternatives +- Never attempt to bypass paywalls + +### 2. JavaScript-Rendered Content + +**Problem**: Some pages load content dynamically via JavaScript, making simple HTTP requests return empty shells. + +**Solutions**: +- Use browser-based fetching tools when available +- Try adding `?format=text` or similar URL parameters +- Look for RSS feeds or API endpoints that serve the same content +- For SPAs, check if there's a server-rendered version + +### 3. Very Long Content + +**Problem**: Documents over 50,000 words may exceed model context limits. + +**Solutions**: +- For PDFs: summarize page-by-page or chapter-by-chapter, then combine +- For webpages: extract only the main article content, skip comments and sidebars +- Use chunked processing: + +```python +def chunk_text(text: str, max_chars: int = 30000) -> list[str]: + """Split text into manageable chunks at paragraph boundaries.""" + paragraphs = text.split('\n\n') + chunks = [] + current = [] + current_len = 0 + + for para in paragraphs: + if current_len + len(para) > max_chars and current: + chunks.append('\n\n'.join(current)) + current = [] + current_len = 0 + current.append(para) + current_len += len(para) + + if current: + chunks.append('\n\n'.join(current)) + + return chunks +``` + +### 4. Non-Text Content + +**Problem**: User provides a file that's primarily images, charts, or scanned documents. + +**Solutions**: +- For scanned PDFs: inform user that OCR is needed (beyond basic scope) +- For image-heavy articles: note that visual content is not captured in the summary +- Suggest tools like Tesseract for OCR if needed + +### 5. Encoding Issues + +**Problem**: Files with unusual encodings (GB2312, Shift-JIS, etc.) may not parse correctly. + +**Solutions**: +- Try common encodings in order: UTF-8, UTF-16, GB2312, GBK, Shift-JIS, Latin-1 +- Use `chardet` library for automatic detection if available + +```python +def read_with_fallback(filepath: str) -> str: + """Read file trying multiple encodings.""" + encodings = ['utf-8', 'utf-8-sig', 'gb2312', 'gbk', 'gb18030', 'shift-jis', 'latin-1'] + for enc in encodings: + try: + with open(filepath, 'r', encoding=enc) as f: + return f.read() + except (UnicodeDecodeError, UnicodeError): + continue + raise ValueError(f"Cannot decode {filepath} with any known encoding") +``` + +### 6. Summarization Quality + +**Problem**: Summaries may miss nuance, oversimplify, or hallucinate details. + +**Solutions**: +- Always attribute the summary to the source +- For critical use cases, recommend the user verify key claims +- When uncertain about content interpretation, flag it explicitly +- Preserve specific numbers, dates, and names rather than generalizing + +### 7. Rate Limits on URL Fetching + +**Problem**: Fetching many URLs quickly may trigger rate limits or blocks. + +**Solutions**: +- Add delays between requests (1-2 seconds) +- Respect robots.txt directives +- Use appropriate User-Agent headers +- Cache fetched content to avoid re-fetching + +--- + +## Multi-AI Model Support + +This skill works with any AI model capable of text summarization. The prompts and workflows are model-agnostic. For best results: + +| Model Capability | Recommended Use | +|---|---| +| Large context window (100K+) | Full document summarization in one pass | +| Standard context (8K-32K) | Chunked processing with merge step | +| Fast inference | Batch processing of multiple sources | +| Multi-language | Cross-language summary generation | + +The skill automatically adapts to the available model's capabilities: +- For large context models: send full content in one request +- For smaller context models: chunk, summarize each, then synthesize +- For multi-modal models: include image descriptions when available diff --git a/account/admin/skills/superpowers-brainstorming/.openakita-i18n.json b/account/admin/skills/superpowers-brainstorming/.openakita-i18n.json new file mode 100644 index 0000000..f78143f --- /dev/null +++ b/account/admin/skills/superpowers-brainstorming/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "头脑风暴设计", + "description": "在编码前通过协作对话探索需求和设计,提出2-3种方案并权衡利弊,确保先设计再实现" + } +} diff --git a/account/admin/skills/superpowers-brainstorming/SKILL.md b/account/admin/skills/superpowers-brainstorming/SKILL.md new file mode 100644 index 0000000..a3d02df --- /dev/null +++ b/account/admin/skills/superpowers-brainstorming/SKILL.md @@ -0,0 +1,96 @@ +--- +name: obra/superpowers@brainstorming +description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation." +--- + +# Brainstorming Ideas Into Designs + +## Overview + +Help turn ideas into fully formed designs and specs through natural collaborative dialogue. + +Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design and get user approval. + + +Do NOT invoke any implementation skill, write any code, scaffold any project, or take any implementation action until you have presented a design and the user has approved it. This applies to EVERY project regardless of perceived simplicity. + + +## Anti-Pattern: "This Is Too Simple To Need A Design" + +Every project goes through this process. A todo list, a single-function utility, a config change — all of them. "Simple" projects are where unexamined assumptions cause the most wasted work. The design can be short (a few sentences for truly simple projects), but you MUST present it and get approval. + +## Checklist + +You MUST create a task for each of these items and complete them in order: + +1. **Explore project context** — check files, docs, recent commits +2. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria +3. **Propose 2-3 approaches** — with trade-offs and your recommendation +4. **Present design** — in sections scaled to their complexity, get user approval after each section +5. **Write design doc** — save to `docs/plans/YYYY-MM-DD--design.md` and commit +6. **Transition to implementation** — invoke writing-plans skill to create implementation plan + +## Process Flow + +```dot +digraph brainstorming { + "Explore project context" [shape=box]; + "Ask clarifying questions" [shape=box]; + "Propose 2-3 approaches" [shape=box]; + "Present design sections" [shape=box]; + "User approves design?" [shape=diamond]; + "Write design doc" [shape=box]; + "Invoke writing-plans skill" [shape=doublecircle]; + + "Explore project context" -> "Ask clarifying questions"; + "Ask clarifying questions" -> "Propose 2-3 approaches"; + "Propose 2-3 approaches" -> "Present design sections"; + "Present design sections" -> "User approves design?"; + "User approves design?" -> "Present design sections" [label="no, revise"]; + "User approves design?" -> "Write design doc" [label="yes"]; + "Write design doc" -> "Invoke writing-plans skill"; +} +``` + +**The terminal state is invoking writing-plans.** Do NOT invoke frontend-design, mcp-builder, or any other implementation skill. The ONLY skill you invoke after brainstorming is writing-plans. + +## The Process + +**Understanding the idea:** +- Check out the current project state first (files, docs, recent commits) +- Ask questions one at a time to refine the idea +- Prefer multiple choice questions when possible, but open-ended is fine too +- Only one question per message - if a topic needs more exploration, break it into multiple questions +- Focus on understanding: purpose, constraints, success criteria + +**Exploring approaches:** +- Propose 2-3 different approaches with trade-offs +- Present options conversationally with your recommendation and reasoning +- Lead with your recommended option and explain why + +**Presenting the design:** +- Once you believe you understand what you're building, present the design +- Scale each section to its complexity: a few sentences if straightforward, up to 200-300 words if nuanced +- Ask after each section whether it looks right so far +- Cover: architecture, components, data flow, error handling, testing +- Be ready to go back and clarify if something doesn't make sense + +## After the Design + +**Documentation:** +- Write the validated design to `docs/plans/YYYY-MM-DD--design.md` +- Use elements-of-style:writing-clearly-and-concisely skill if available +- Commit the design document to git + +**Implementation:** +- Invoke the writing-plans skill to create a detailed implementation plan +- Do NOT invoke any other skill. writing-plans is the next step. + +## Key Principles + +- **One question at a time** - Don't overwhelm with multiple questions +- **Multiple choice preferred** - Easier to answer than open-ended when possible +- **YAGNI ruthlessly** - Remove unnecessary features from all designs +- **Explore alternatives** - Always propose 2-3 approaches before settling +- **Incremental validation** - Present design, get approval before moving on +- **Be flexible** - Go back and clarify when something doesn't make sense diff --git a/account/admin/skills/superpowers-debugging/.openakita-i18n.json b/account/admin/skills/superpowers-debugging/.openakita-i18n.json new file mode 100644 index 0000000..eef27ce --- /dev/null +++ b/account/admin/skills/superpowers-debugging/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "系统化调试", + "description": "结构化的 Bug 调试流程:收集证据、形成假设、二分验证,避免盲目修改代码" + } +} diff --git a/account/admin/skills/superpowers-debugging/SKILL.md b/account/admin/skills/superpowers-debugging/SKILL.md new file mode 100644 index 0000000..4ddb4d2 --- /dev/null +++ b/account/admin/skills/superpowers-debugging/SKILL.md @@ -0,0 +1,296 @@ +--- +name: obra/superpowers@systematic-debugging +description: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes +--- + +# Systematic Debugging + +## Overview + +Random fixes waste time and create new bugs. Quick patches mask underlying issues. + +**Core principle:** ALWAYS find root cause before attempting fixes. Symptom fixes are failure. + +**Violating the letter of this process is violating the spirit of debugging.** + +## The Iron Law + +``` +NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST +``` + +If you haven't completed Phase 1, you cannot propose fixes. + +## When to Use + +Use for ANY technical issue: +- Test failures +- Bugs in production +- Unexpected behavior +- Performance problems +- Build failures +- Integration issues + +**Use this ESPECIALLY when:** +- Under time pressure (emergencies make guessing tempting) +- "Just one quick fix" seems obvious +- You've already tried multiple fixes +- Previous fix didn't work +- You don't fully understand the issue + +**Don't skip when:** +- Issue seems simple (simple bugs have root causes too) +- You're in a hurry (rushing guarantees rework) +- Manager wants it fixed NOW (systematic is faster than thrashing) + +## The Four Phases + +You MUST complete each phase before proceeding to the next. + +### Phase 1: Root Cause Investigation + +**BEFORE attempting ANY fix:** + +1. **Read Error Messages Carefully** + - Don't skip past errors or warnings + - They often contain the exact solution + - Read stack traces completely + - Note line numbers, file paths, error codes + +2. **Reproduce Consistently** + - Can you trigger it reliably? + - What are the exact steps? + - Does it happen every time? + - If not reproducible → gather more data, don't guess + +3. **Check Recent Changes** + - What changed that could cause this? + - Git diff, recent commits + - New dependencies, config changes + - Environmental differences + +4. **Gather Evidence in Multi-Component Systems** + + **WHEN system has multiple components (CI → build → signing, API → service → database):** + + **BEFORE proposing fixes, add diagnostic instrumentation:** + ``` + For EACH component boundary: + - Log what data enters component + - Log what data exits component + - Verify environment/config propagation + - Check state at each layer + + Run once to gather evidence showing WHERE it breaks + THEN analyze evidence to identify failing component + THEN investigate that specific component + ``` + + **Example (multi-layer system):** + ```bash + # Layer 1: Workflow + echo "=== Secrets available in workflow: ===" + echo "IDENTITY: ${IDENTITY:+SET}${IDENTITY:-UNSET}" + + # Layer 2: Build script + echo "=== Env vars in build script: ===" + env | grep IDENTITY || echo "IDENTITY not in environment" + + # Layer 3: Signing script + echo "=== Keychain state: ===" + security list-keychains + security find-identity -v + + # Layer 4: Actual signing + codesign --sign "$IDENTITY" --verbose=4 "$APP" + ``` + + **This reveals:** Which layer fails (secrets → workflow ✓, workflow → build ✗) + +5. **Trace Data Flow** + + **WHEN error is deep in call stack:** + + See `root-cause-tracing.md` in this directory for the complete backward tracing technique. + + **Quick version:** + - Where does bad value originate? + - What called this with bad value? + - Keep tracing up until you find the source + - Fix at source, not at symptom + +### Phase 2: Pattern Analysis + +**Find the pattern before fixing:** + +1. **Find Working Examples** + - Locate similar working code in same codebase + - What works that's similar to what's broken? + +2. **Compare Against References** + - If implementing pattern, read reference implementation COMPLETELY + - Don't skim - read every line + - Understand the pattern fully before applying + +3. **Identify Differences** + - What's different between working and broken? + - List every difference, however small + - Don't assume "that can't matter" + +4. **Understand Dependencies** + - What other components does this need? + - What settings, config, environment? + - What assumptions does it make? + +### Phase 3: Hypothesis and Testing + +**Scientific method:** + +1. **Form Single Hypothesis** + - State clearly: "I think X is the root cause because Y" + - Write it down + - Be specific, not vague + +2. **Test Minimally** + - Make the SMALLEST possible change to test hypothesis + - One variable at a time + - Don't fix multiple things at once + +3. **Verify Before Continuing** + - Did it work? Yes → Phase 4 + - Didn't work? Form NEW hypothesis + - DON'T add more fixes on top + +4. **When You Don't Know** + - Say "I don't understand X" + - Don't pretend to know + - Ask for help + - Research more + +### Phase 4: Implementation + +**Fix the root cause, not the symptom:** + +1. **Create Failing Test Case** + - Simplest possible reproduction + - Automated test if possible + - One-off test script if no framework + - MUST have before fixing + - Use the `superpowers:test-driven-development` skill for writing proper failing tests + +2. **Implement Single Fix** + - Address the root cause identified + - ONE change at a time + - No "while I'm here" improvements + - No bundled refactoring + +3. **Verify Fix** + - Test passes now? + - No other tests broken? + - Issue actually resolved? + +4. **If Fix Doesn't Work** + - STOP + - Count: How many fixes have you tried? + - If < 3: Return to Phase 1, re-analyze with new information + - **If ≥ 3: STOP and question the architecture (step 5 below)** + - DON'T attempt Fix #4 without architectural discussion + +5. **If 3+ Fixes Failed: Question Architecture** + + **Pattern indicating architectural problem:** + - Each fix reveals new shared state/coupling/problem in different place + - Fixes require "massive refactoring" to implement + - Each fix creates new symptoms elsewhere + + **STOP and question fundamentals:** + - Is this pattern fundamentally sound? + - Are we "sticking with it through sheer inertia"? + - Should we refactor architecture vs. continue fixing symptoms? + + **Discuss with your human partner before attempting more fixes** + + This is NOT a failed hypothesis - this is a wrong architecture. + +## Red Flags - STOP and Follow Process + +If you catch yourself thinking: +- "Quick fix for now, investigate later" +- "Just try changing X and see if it works" +- "Add multiple changes, run tests" +- "Skip the test, I'll manually verify" +- "It's probably X, let me fix that" +- "I don't fully understand but this might work" +- "Pattern says X but I'll adapt it differently" +- "Here are the main problems: [lists fixes without investigation]" +- Proposing solutions before tracing data flow +- **"One more fix attempt" (when already tried 2+)** +- **Each fix reveals new problem in different place** + +**ALL of these mean: STOP. Return to Phase 1.** + +**If 3+ fixes failed:** Question the architecture (see Phase 4.5) + +## your human partner's Signals You're Doing It Wrong + +**Watch for these redirections:** +- "Is that not happening?" - You assumed without verifying +- "Will it show us...?" - You should have added evidence gathering +- "Stop guessing" - You're proposing fixes without understanding +- "Ultrathink this" - Question fundamentals, not just symptoms +- "We're stuck?" (frustrated) - Your approach isn't working + +**When you see these:** STOP. Return to Phase 1. + +## Common Rationalizations + +| Excuse | Reality | +|--------|---------| +| "Issue is simple, don't need process" | Simple issues have root causes too. Process is fast for simple bugs. | +| "Emergency, no time for process" | Systematic debugging is FASTER than guess-and-check thrashing. | +| "Just try this first, then investigate" | First fix sets the pattern. Do it right from the start. | +| "I'll write test after confirming fix works" | Untested fixes don't stick. Test first proves it. | +| "Multiple fixes at once saves time" | Can't isolate what worked. Causes new bugs. | +| "Reference too long, I'll adapt the pattern" | Partial understanding guarantees bugs. Read it completely. | +| "I see the problem, let me fix it" | Seeing symptoms ≠ understanding root cause. | +| "One more fix attempt" (after 2+ failures) | 3+ failures = architectural problem. Question pattern, don't fix again. | + +## Quick Reference + +| Phase | Key Activities | Success Criteria | +|-------|---------------|------------------| +| **1. Root Cause** | Read errors, reproduce, check changes, gather evidence | Understand WHAT and WHY | +| **2. Pattern** | Find working examples, compare | Identify differences | +| **3. Hypothesis** | Form theory, test minimally | Confirmed or new hypothesis | +| **4. Implementation** | Create test, fix, verify | Bug resolved, tests pass | + +## When Process Reveals "No Root Cause" + +If systematic investigation reveals issue is truly environmental, timing-dependent, or external: + +1. You've completed the process +2. Document what you investigated +3. Implement appropriate handling (retry, timeout, error message) +4. Add monitoring/logging for future investigation + +**But:** 95% of "no root cause" cases are incomplete investigation. + +## Supporting Techniques + +These techniques are part of systematic debugging and available in this directory: + +- **`root-cause-tracing.md`** - Trace bugs backward through call stack to find original trigger +- **`defense-in-depth.md`** - Add validation at multiple layers after finding root cause +- **`condition-based-waiting.md`** - Replace arbitrary timeouts with condition polling + +**Related skills:** +- **superpowers:test-driven-development** - For creating failing test case (Phase 4, Step 1) +- **superpowers:verification-before-completion** - Verify fix worked before claiming success + +## Real-World Impact + +From debugging sessions: +- Systematic approach: 15-30 minutes to fix +- Random fixes approach: 2-3 hours of thrashing +- First-time fix rate: 95% vs 40% +- New bugs introduced: Near zero vs common diff --git a/account/admin/skills/superpowers-dispatching-agents/.openakita-i18n.json b/account/admin/skills/superpowers-dispatching-agents/.openakita-i18n.json new file mode 100644 index 0000000..9658a48 --- /dev/null +++ b/account/admin/skills/superpowers-dispatching-agents/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "并行 Agent 调度", + "description": "将复杂任务分解为独立子任务,派发给多个并行 Agent 执行,提高效率" + } +} diff --git a/account/admin/skills/superpowers-dispatching-agents/SKILL.md b/account/admin/skills/superpowers-dispatching-agents/SKILL.md new file mode 100644 index 0000000..1ffbcc3 --- /dev/null +++ b/account/admin/skills/superpowers-dispatching-agents/SKILL.md @@ -0,0 +1,180 @@ +--- +name: obra/superpowers@dispatching-parallel-agents +description: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies +--- + +# Dispatching Parallel Agents + +## Overview + +When you have multiple unrelated failures (different test files, different subsystems, different bugs), investigating them sequentially wastes time. Each investigation is independent and can happen in parallel. + +**Core principle:** Dispatch one agent per independent problem domain. Let them work concurrently. + +## When to Use + +```dot +digraph when_to_use { + "Multiple failures?" [shape=diamond]; + "Are they independent?" [shape=diamond]; + "Single agent investigates all" [shape=box]; + "One agent per problem domain" [shape=box]; + "Can they work in parallel?" [shape=diamond]; + "Sequential agents" [shape=box]; + "Parallel dispatch" [shape=box]; + + "Multiple failures?" -> "Are they independent?" [label="yes"]; + "Are they independent?" -> "Single agent investigates all" [label="no - related"]; + "Are they independent?" -> "Can they work in parallel?" [label="yes"]; + "Can they work in parallel?" -> "Parallel dispatch" [label="yes"]; + "Can they work in parallel?" -> "Sequential agents" [label="no - shared state"]; +} +``` + +**Use when:** +- 3+ test files failing with different root causes +- Multiple subsystems broken independently +- Each problem can be understood without context from others +- No shared state between investigations + +**Don't use when:** +- Failures are related (fix one might fix others) +- Need to understand full system state +- Agents would interfere with each other + +## The Pattern + +### 1. Identify Independent Domains + +Group failures by what's broken: +- File A tests: Tool approval flow +- File B tests: Batch completion behavior +- File C tests: Abort functionality + +Each domain is independent - fixing tool approval doesn't affect abort tests. + +### 2. Create Focused Agent Tasks + +Each agent gets: +- **Specific scope:** One test file or subsystem +- **Clear goal:** Make these tests pass +- **Constraints:** Don't change other code +- **Expected output:** Summary of what you found and fixed + +### 3. Dispatch in Parallel + +```typescript +// In Claude Code / AI environment +Task("Fix agent-tool-abort.test.ts failures") +Task("Fix batch-completion-behavior.test.ts failures") +Task("Fix tool-approval-race-conditions.test.ts failures") +// All three run concurrently +``` + +### 4. Review and Integrate + +When agents return: +- Read each summary +- Verify fixes don't conflict +- Run full test suite +- Integrate all changes + +## Agent Prompt Structure + +Good agent prompts are: +1. **Focused** - One clear problem domain +2. **Self-contained** - All context needed to understand the problem +3. **Specific about output** - What should the agent return? + +```markdown +Fix the 3 failing tests in src/agents/agent-tool-abort.test.ts: + +1. "should abort tool with partial output capture" - expects 'interrupted at' in message +2. "should handle mixed completed and aborted tools" - fast tool aborted instead of completed +3. "should properly track pendingToolCount" - expects 3 results but gets 0 + +These are timing/race condition issues. Your task: + +1. Read the test file and understand what each test verifies +2. Identify root cause - timing issues or actual bugs? +3. Fix by: + - Replacing arbitrary timeouts with event-based waiting + - Fixing bugs in abort implementation if found + - Adjusting test expectations if testing changed behavior + +Do NOT just increase timeouts - find the real issue. + +Return: Summary of what you found and what you fixed. +``` + +## Common Mistakes + +**❌ Too broad:** "Fix all the tests" - agent gets lost +**✅ Specific:** "Fix agent-tool-abort.test.ts" - focused scope + +**❌ No context:** "Fix the race condition" - agent doesn't know where +**✅ Context:** Paste the error messages and test names + +**❌ No constraints:** Agent might refactor everything +**✅ Constraints:** "Do NOT change production code" or "Fix tests only" + +**❌ Vague output:** "Fix it" - you don't know what changed +**✅ Specific:** "Return summary of root cause and changes" + +## When NOT to Use + +**Related failures:** Fixing one might fix others - investigate together first +**Need full context:** Understanding requires seeing entire system +**Exploratory debugging:** You don't know what's broken yet +**Shared state:** Agents would interfere (editing same files, using same resources) + +## Real Example from Session + +**Scenario:** 6 test failures across 3 files after major refactoring + +**Failures:** +- agent-tool-abort.test.ts: 3 failures (timing issues) +- batch-completion-behavior.test.ts: 2 failures (tools not executing) +- tool-approval-race-conditions.test.ts: 1 failure (execution count = 0) + +**Decision:** Independent domains - abort logic separate from batch completion separate from race conditions + +**Dispatch:** +``` +Agent 1 → Fix agent-tool-abort.test.ts +Agent 2 → Fix batch-completion-behavior.test.ts +Agent 3 → Fix tool-approval-race-conditions.test.ts +``` + +**Results:** +- Agent 1: Replaced timeouts with event-based waiting +- Agent 2: Fixed event structure bug (threadId in wrong place) +- Agent 3: Added wait for async tool execution to complete + +**Integration:** All fixes independent, no conflicts, full suite green + +**Time saved:** 3 problems solved in parallel vs sequentially + +## Key Benefits + +1. **Parallelization** - Multiple investigations happen simultaneously +2. **Focus** - Each agent has narrow scope, less context to track +3. **Independence** - Agents don't interfere with each other +4. **Speed** - 3 problems solved in time of 1 + +## Verification + +After agents return: +1. **Review each summary** - Understand what changed +2. **Check for conflicts** - Did agents edit same code? +3. **Run full suite** - Verify all fixes work together +4. **Spot check** - Agents can make systematic errors + +## Real-World Impact + +From debugging session (2025-10-03): +- 6 failures across 3 files +- 3 agents dispatched in parallel +- All investigations completed concurrently +- All fixes integrated successfully +- Zero conflicts between agent changes diff --git a/account/admin/skills/superpowers-executing-plans/.openakita-i18n.json b/account/admin/skills/superpowers-executing-plans/.openakita-i18n.json new file mode 100644 index 0000000..81b8983 --- /dev/null +++ b/account/admin/skills/superpowers-executing-plans/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "执行计划", + "description": "按步骤执行实施计划,每个任务完成后验证结果,确保高质量交付" + } +} diff --git a/account/admin/skills/superpowers-executing-plans/SKILL.md b/account/admin/skills/superpowers-executing-plans/SKILL.md new file mode 100644 index 0000000..0635f76 --- /dev/null +++ b/account/admin/skills/superpowers-executing-plans/SKILL.md @@ -0,0 +1,84 @@ +--- +name: obra/superpowers@executing-plans +description: Use when you have a written implementation plan to execute in a separate session with review checkpoints +--- + +# Executing Plans + +## Overview + +Load plan, review critically, execute tasks in batches, report for review between batches. + +**Core principle:** Batch execution with checkpoints for architect review. + +**Announce at start:** "I'm using the executing-plans skill to implement this plan." + +## The Process + +### Step 1: Load and Review Plan +1. Read plan file +2. Review critically - identify any questions or concerns about the plan +3. If concerns: Raise them with your human partner before starting +4. If no concerns: Create TodoWrite and proceed + +### Step 2: Execute Batch +**Default: First 3 tasks** + +For each task: +1. Mark as in_progress +2. Follow each step exactly (plan has bite-sized steps) +3. Run verifications as specified +4. Mark as completed + +### Step 3: Report +When batch complete: +- Show what was implemented +- Show verification output +- Say: "Ready for feedback." + +### Step 4: Continue +Based on feedback: +- Apply changes if needed +- Execute next batch +- Repeat until complete + +### Step 5: Complete Development + +After all tasks complete and verified: +- Announce: "I'm using the finishing-a-development-branch skill to complete this work." +- **REQUIRED SUB-SKILL:** Use superpowers:finishing-a-development-branch +- Follow that skill to verify tests, present options, execute choice + +## When to Stop and Ask for Help + +**STOP executing immediately when:** +- Hit a blocker mid-batch (missing dependency, test fails, instruction unclear) +- Plan has critical gaps preventing starting +- You don't understand an instruction +- Verification fails repeatedly + +**Ask for clarification rather than guessing.** + +## When to Revisit Earlier Steps + +**Return to Review (Step 1) when:** +- Partner updates the plan based on your feedback +- Fundamental approach needs rethinking + +**Don't force through blockers** - stop and ask. + +## Remember +- Review plan critically first +- Follow plan steps exactly +- Don't skip verifications +- Reference skills when plan says to +- Between batches: just report and wait +- Stop when blocked, don't guess +- Never start implementation on main/master branch without explicit user consent + +## Integration + +**Required workflow skills:** +- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting +- **superpowers:writing-plans** - Creates the plan this skill executes +- **superpowers:finishing-a-development-branch** - Complete development after all tasks diff --git a/account/admin/skills/superpowers-finishing-branch/.openakita-i18n.json b/account/admin/skills/superpowers-finishing-branch/.openakita-i18n.json new file mode 100644 index 0000000..c32dc1e --- /dev/null +++ b/account/admin/skills/superpowers-finishing-branch/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "完成开发分支", + "description": "开发分支收尾流程:代码审查、测试验证、合并准备,确保分支干净完整" + } +} diff --git a/account/admin/skills/superpowers-finishing-branch/SKILL.md b/account/admin/skills/superpowers-finishing-branch/SKILL.md new file mode 100644 index 0000000..58fd601 --- /dev/null +++ b/account/admin/skills/superpowers-finishing-branch/SKILL.md @@ -0,0 +1,200 @@ +--- +name: obra/superpowers@finishing-a-development-branch +description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup +--- + +# Finishing a Development Branch + +## Overview + +Guide completion of development work by presenting clear options and handling chosen workflow. + +**Core principle:** Verify tests → Present options → Execute choice → Clean up. + +**Announce at start:** "I'm using the finishing-a-development-branch skill to complete this work." + +## The Process + +### Step 1: Verify Tests + +**Before presenting options, verify tests pass:** + +```bash +# Run project's test suite +npm test / cargo test / pytest / go test ./... +``` + +**If tests fail:** +``` +Tests failing ( failures). Must fix before completing: + +[Show failures] + +Cannot proceed with merge/PR until tests pass. +``` + +Stop. Don't proceed to Step 2. + +**If tests pass:** Continue to Step 2. + +### Step 2: Determine Base Branch + +```bash +# Try common base branches +git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null +``` + +Or ask: "This branch split from main - is that correct?" + +### Step 3: Present Options + +Present exactly these 4 options: + +``` +Implementation complete. What would you like to do? + +1. Merge back to locally +2. Push and create a Pull Request +3. Keep the branch as-is (I'll handle it later) +4. Discard this work + +Which option? +``` + +**Don't add explanation** - keep options concise. + +### Step 4: Execute Choice + +#### Option 1: Merge Locally + +```bash +# Switch to base branch +git checkout + +# Pull latest +git pull + +# Merge feature branch +git merge + +# Verify tests on merged result + + +# If tests pass +git branch -d +``` + +Then: Cleanup worktree (Step 5) + +#### Option 2: Push and Create PR + +```bash +# Push branch +git push -u origin + +# Create PR +gh pr create --title "" --body "$(cat <<'EOF' +## Summary +<2-3 bullets of what changed> + +## Test Plan +- [ ] <verification steps> +EOF +)" +``` + +Then: Cleanup worktree (Step 5) + +#### Option 3: Keep As-Is + +Report: "Keeping branch <name>. Worktree preserved at <path>." + +**Don't cleanup worktree.** + +#### Option 4: Discard + +**Confirm first:** +``` +This will permanently delete: +- Branch <name> +- All commits: <commit-list> +- Worktree at <path> + +Type 'discard' to confirm. +``` + +Wait for exact confirmation. + +If confirmed: +```bash +git checkout <base-branch> +git branch -D <feature-branch> +``` + +Then: Cleanup worktree (Step 5) + +### Step 5: Cleanup Worktree + +**For Options 1, 2, 4:** + +Check if in worktree: +```bash +git worktree list | grep $(git branch --show-current) +``` + +If yes: +```bash +git worktree remove <worktree-path> +``` + +**For Option 3:** Keep worktree. + +## Quick Reference + +| Option | Merge | Push | Keep Worktree | Cleanup Branch | +|--------|-------|------|---------------|----------------| +| 1. Merge locally | ✓ | - | - | ✓ | +| 2. Create PR | - | ✓ | ✓ | - | +| 3. Keep as-is | - | - | ✓ | - | +| 4. Discard | - | - | - | ✓ (force) | + +## Common Mistakes + +**Skipping test verification** +- **Problem:** Merge broken code, create failing PR +- **Fix:** Always verify tests before offering options + +**Open-ended questions** +- **Problem:** "What should I do next?" → ambiguous +- **Fix:** Present exactly 4 structured options + +**Automatic worktree cleanup** +- **Problem:** Remove worktree when might need it (Option 2, 3) +- **Fix:** Only cleanup for Options 1 and 4 + +**No confirmation for discard** +- **Problem:** Accidentally delete work +- **Fix:** Require typed "discard" confirmation + +## Red Flags + +**Never:** +- Proceed with failing tests +- Merge without verifying tests on result +- Delete work without confirmation +- Force-push without explicit request + +**Always:** +- Verify tests before offering options +- Present exactly 4 options +- Get typed confirmation for Option 4 +- Clean up worktree for Options 1 & 4 only + +## Integration + +**Called by:** +- **subagent-driven-development** (Step 7) - After all tasks complete +- **executing-plans** (Step 5) - After all batches complete + +**Pairs with:** +- **using-git-worktrees** - Cleans up worktree created by that skill diff --git a/account/admin/skills/superpowers-git-worktrees/.openakita-i18n.json b/account/admin/skills/superpowers-git-worktrees/.openakita-i18n.json new file mode 100644 index 0000000..1627c3f --- /dev/null +++ b/account/admin/skills/superpowers-git-worktrees/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Git Worktree 工作流", + "description": "使用 Git Worktree 在独立工作空间开发,避免分支切换干扰,支持并行开发" + } +} diff --git a/account/admin/skills/superpowers-git-worktrees/SKILL.md b/account/admin/skills/superpowers-git-worktrees/SKILL.md new file mode 100644 index 0000000..97e810a --- /dev/null +++ b/account/admin/skills/superpowers-git-worktrees/SKILL.md @@ -0,0 +1,218 @@ +--- +name: obra/superpowers@using-git-worktrees +description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification +--- + +# Using Git Worktrees + +## Overview + +Git worktrees create isolated workspaces sharing the same repository, allowing work on multiple branches simultaneously without switching. + +**Core principle:** Systematic directory selection + safety verification = reliable isolation. + +**Announce at start:** "I'm using the using-git-worktrees skill to set up an isolated workspace." + +## Directory Selection Process + +Follow this priority order: + +### 1. Check Existing Directories + +```bash +# Check in priority order +ls -d .worktrees 2>/dev/null # Preferred (hidden) +ls -d worktrees 2>/dev/null # Alternative +``` + +**If found:** Use that directory. If both exist, `.worktrees` wins. + +### 2. Check CLAUDE.md + +```bash +grep -i "worktree.*director" CLAUDE.md 2>/dev/null +``` + +**If preference specified:** Use it without asking. + +### 3. Ask User + +If no directory exists and no CLAUDE.md preference: + +``` +No worktree directory found. Where should I create worktrees? + +1. .worktrees/ (project-local, hidden) +2. ~/.config/superpowers/worktrees/<project-name>/ (global location) + +Which would you prefer? +``` + +## Safety Verification + +### For Project-Local Directories (.worktrees or worktrees) + +**MUST verify directory is ignored before creating worktree:** + +```bash +# Check if directory is ignored (respects local, global, and system gitignore) +git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null +``` + +**If NOT ignored:** + +Per Jesse's rule "Fix broken things immediately": +1. Add appropriate line to .gitignore +2. Commit the change +3. Proceed with worktree creation + +**Why critical:** Prevents accidentally committing worktree contents to repository. + +### For Global Directory (~/.config/superpowers/worktrees) + +No .gitignore verification needed - outside project entirely. + +## Creation Steps + +### 1. Detect Project Name + +```bash +project=$(basename "$(git rev-parse --show-toplevel)") +``` + +### 2. Create Worktree + +```bash +# Determine full path +case $LOCATION in + .worktrees|worktrees) + path="$LOCATION/$BRANCH_NAME" + ;; + ~/.config/superpowers/worktrees/*) + path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME" + ;; +esac + +# Create worktree with new branch +git worktree add "$path" -b "$BRANCH_NAME" +cd "$path" +``` + +### 3. Run Project Setup + +Auto-detect and run appropriate setup: + +```bash +# Node.js +if [ -f package.json ]; then npm install; fi + +# Rust +if [ -f Cargo.toml ]; then cargo build; fi + +# Python +if [ -f requirements.txt ]; then pip install -r requirements.txt; fi +if [ -f pyproject.toml ]; then poetry install; fi + +# Go +if [ -f go.mod ]; then go mod download; fi +``` + +### 4. Verify Clean Baseline + +Run tests to ensure worktree starts clean: + +```bash +# Examples - use project-appropriate command +npm test +cargo test +pytest +go test ./... +``` + +**If tests fail:** Report failures, ask whether to proceed or investigate. + +**If tests pass:** Report ready. + +### 5. Report Location + +``` +Worktree ready at <full-path> +Tests passing (<N> tests, 0 failures) +Ready to implement <feature-name> +``` + +## Quick Reference + +| Situation | Action | +|-----------|--------| +| `.worktrees/` exists | Use it (verify ignored) | +| `worktrees/` exists | Use it (verify ignored) | +| Both exist | Use `.worktrees/` | +| Neither exists | Check CLAUDE.md → Ask user | +| Directory not ignored | Add to .gitignore + commit | +| Tests fail during baseline | Report failures + ask | +| No package.json/Cargo.toml | Skip dependency install | + +## Common Mistakes + +### Skipping ignore verification + +- **Problem:** Worktree contents get tracked, pollute git status +- **Fix:** Always use `git check-ignore` before creating project-local worktree + +### Assuming directory location + +- **Problem:** Creates inconsistency, violates project conventions +- **Fix:** Follow priority: existing > CLAUDE.md > ask + +### Proceeding with failing tests + +- **Problem:** Can't distinguish new bugs from pre-existing issues +- **Fix:** Report failures, get explicit permission to proceed + +### Hardcoding setup commands + +- **Problem:** Breaks on projects using different tools +- **Fix:** Auto-detect from project files (package.json, etc.) + +## Example Workflow + +``` +You: I'm using the using-git-worktrees skill to set up an isolated workspace. + +[Check .worktrees/ - exists] +[Verify ignored - git check-ignore confirms .worktrees/ is ignored] +[Create worktree: git worktree add .worktrees/auth -b feature/auth] +[Run npm install] +[Run npm test - 47 passing] + +Worktree ready at /Users/jesse/myproject/.worktrees/auth +Tests passing (47 tests, 0 failures) +Ready to implement auth feature +``` + +## Red Flags + +**Never:** +- Create worktree without verifying it's ignored (project-local) +- Skip baseline test verification +- Proceed with failing tests without asking +- Assume directory location when ambiguous +- Skip CLAUDE.md check + +**Always:** +- Follow directory priority: existing > CLAUDE.md > ask +- Verify directory is ignored for project-local +- Auto-detect and run project setup +- Verify clean test baseline + +## Integration + +**Called by:** +- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows +- **subagent-driven-development** - REQUIRED before executing any tasks +- **executing-plans** - REQUIRED before executing any tasks +- Any skill needing isolated workspace + +**Pairs with:** +- **finishing-a-development-branch** - REQUIRED for cleanup after work complete diff --git a/account/admin/skills/superpowers-receiving-review/.openakita-i18n.json b/account/admin/skills/superpowers-receiving-review/.openakita-i18n.json new file mode 100644 index 0000000..d9f0e86 --- /dev/null +++ b/account/admin/skills/superpowers-receiving-review/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "接收代码评审", + "description": "处理代码评审反馈:理解评论、分类问题、逐项修复、验证后回复" + } +} diff --git a/account/admin/skills/superpowers-receiving-review/SKILL.md b/account/admin/skills/superpowers-receiving-review/SKILL.md new file mode 100644 index 0000000..0cd1d2e --- /dev/null +++ b/account/admin/skills/superpowers-receiving-review/SKILL.md @@ -0,0 +1,213 @@ +--- +name: obra/superpowers@receiving-code-review +description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation +--- + +# Code Review Reception + +## Overview + +Code review requires technical evaluation, not emotional performance. + +**Core principle:** Verify before implementing. Ask before assuming. Technical correctness over social comfort. + +## The Response Pattern + +``` +WHEN receiving code review feedback: + +1. READ: Complete feedback without reacting +2. UNDERSTAND: Restate requirement in own words (or ask) +3. VERIFY: Check against codebase reality +4. EVALUATE: Technically sound for THIS codebase? +5. RESPOND: Technical acknowledgment or reasoned pushback +6. IMPLEMENT: One item at a time, test each +``` + +## Forbidden Responses + +**NEVER:** +- "You're absolutely right!" (explicit CLAUDE.md violation) +- "Great point!" / "Excellent feedback!" (performative) +- "Let me implement that now" (before verification) + +**INSTEAD:** +- Restate the technical requirement +- Ask clarifying questions +- Push back with technical reasoning if wrong +- Just start working (actions > words) + +## Handling Unclear Feedback + +``` +IF any item is unclear: + STOP - do not implement anything yet + ASK for clarification on unclear items + +WHY: Items may be related. Partial understanding = wrong implementation. +``` + +**Example:** +``` +your human partner: "Fix 1-6" +You understand 1,2,3,6. Unclear on 4,5. + +❌ WRONG: Implement 1,2,3,6 now, ask about 4,5 later +✅ RIGHT: "I understand items 1,2,3,6. Need clarification on 4 and 5 before proceeding." +``` + +## Source-Specific Handling + +### From your human partner +- **Trusted** - implement after understanding +- **Still ask** if scope unclear +- **No performative agreement** +- **Skip to action** or technical acknowledgment + +### From External Reviewers +``` +BEFORE implementing: + 1. Check: Technically correct for THIS codebase? + 2. Check: Breaks existing functionality? + 3. Check: Reason for current implementation? + 4. Check: Works on all platforms/versions? + 5. Check: Does reviewer understand full context? + +IF suggestion seems wrong: + Push back with technical reasoning + +IF can't easily verify: + Say so: "I can't verify this without [X]. Should I [investigate/ask/proceed]?" + +IF conflicts with your human partner's prior decisions: + Stop and discuss with your human partner first +``` + +**your human partner's rule:** "External feedback - be skeptical, but check carefully" + +## YAGNI Check for "Professional" Features + +``` +IF reviewer suggests "implementing properly": + grep codebase for actual usage + + IF unused: "This endpoint isn't called. Remove it (YAGNI)?" + IF used: Then implement properly +``` + +**your human partner's rule:** "You and reviewer both report to me. If we don't need this feature, don't add it." + +## Implementation Order + +``` +FOR multi-item feedback: + 1. Clarify anything unclear FIRST + 2. Then implement in this order: + - Blocking issues (breaks, security) + - Simple fixes (typos, imports) + - Complex fixes (refactoring, logic) + 3. Test each fix individually + 4. Verify no regressions +``` + +## When To Push Back + +Push back when: +- Suggestion breaks existing functionality +- Reviewer lacks full context +- Violates YAGNI (unused feature) +- Technically incorrect for this stack +- Legacy/compatibility reasons exist +- Conflicts with your human partner's architectural decisions + +**How to push back:** +- Use technical reasoning, not defensiveness +- Ask specific questions +- Reference working tests/code +- Involve your human partner if architectural + +**Signal if uncomfortable pushing back out loud:** "Strange things are afoot at the Circle K" + +## Acknowledging Correct Feedback + +When feedback IS correct: +``` +✅ "Fixed. [Brief description of what changed]" +✅ "Good catch - [specific issue]. Fixed in [location]." +✅ [Just fix it and show in the code] + +❌ "You're absolutely right!" +❌ "Great point!" +❌ "Thanks for catching that!" +❌ "Thanks for [anything]" +❌ ANY gratitude expression +``` + +**Why no thanks:** Actions speak. Just fix it. The code itself shows you heard the feedback. + +**If you catch yourself about to write "Thanks":** DELETE IT. State the fix instead. + +## Gracefully Correcting Your Pushback + +If you pushed back and were wrong: +``` +✅ "You were right - I checked [X] and it does [Y]. Implementing now." +✅ "Verified this and you're correct. My initial understanding was wrong because [reason]. Fixing." + +❌ Long apology +❌ Defending why you pushed back +❌ Over-explaining +``` + +State the correction factually and move on. + +## Common Mistakes + +| Mistake | Fix | +|---------|-----| +| Performative agreement | State requirement or just act | +| Blind implementation | Verify against codebase first | +| Batch without testing | One at a time, test each | +| Assuming reviewer is right | Check if breaks things | +| Avoiding pushback | Technical correctness > comfort | +| Partial implementation | Clarify all items first | +| Can't verify, proceed anyway | State limitation, ask for direction | + +## Real Examples + +**Performative Agreement (Bad):** +``` +Reviewer: "Remove legacy code" +❌ "You're absolutely right! Let me remove that..." +``` + +**Technical Verification (Good):** +``` +Reviewer: "Remove legacy code" +✅ "Checking... build target is 10.15+, this API needs 13+. Need legacy for backward compat. Current impl has wrong bundle ID - fix it or drop pre-13 support?" +``` + +**YAGNI (Good):** +``` +Reviewer: "Implement proper metrics tracking with database, date filters, CSV export" +✅ "Grepped codebase - nothing calls this endpoint. Remove it (YAGNI)? Or is there usage I'm missing?" +``` + +**Unclear Item (Good):** +``` +your human partner: "Fix items 1-6" +You understand 1,2,3,6. Unclear on 4,5. +✅ "Understand 1,2,3,6. Need clarification on 4 and 5 before implementing." +``` + +## GitHub Thread Replies + +When replying to inline review comments on GitHub, reply in the comment thread (`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`), not as a top-level PR comment. + +## The Bottom Line + +**External feedback = suggestions to evaluate, not orders to follow.** + +Verify. Question. Then implement. + +No performative agreement. Technical rigor always. diff --git a/account/admin/skills/superpowers-requesting-review/.openakita-i18n.json b/account/admin/skills/superpowers-requesting-review/.openakita-i18n.json new file mode 100644 index 0000000..ebf2be5 --- /dev/null +++ b/account/admin/skills/superpowers-requesting-review/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "请求代码评审", + "description": "发起代码评审请求:准备变更摘要、标注关注点、提供上下文" + } +} diff --git a/account/admin/skills/superpowers-requesting-review/SKILL.md b/account/admin/skills/superpowers-requesting-review/SKILL.md new file mode 100644 index 0000000..dca7674 --- /dev/null +++ b/account/admin/skills/superpowers-requesting-review/SKILL.md @@ -0,0 +1,105 @@ +--- +name: obra/superpowers@requesting-code-review +description: Use when completing tasks, implementing major features, or before merging to verify work meets requirements +--- + +# Requesting Code Review + +Dispatch superpowers:code-reviewer subagent to catch issues before they cascade. + +**Core principle:** Review early, review often. + +## When to Request Review + +**Mandatory:** +- After each task in subagent-driven development +- After completing major feature +- Before merge to main + +**Optional but valuable:** +- When stuck (fresh perspective) +- Before refactoring (baseline check) +- After fixing complex bug + +## How to Request + +**1. Get git SHAs:** +```bash +BASE_SHA=$(git rev-parse HEAD~1) # or origin/main +HEAD_SHA=$(git rev-parse HEAD) +``` + +**2. Dispatch code-reviewer subagent:** + +Use Task tool with superpowers:code-reviewer type, fill template at `code-reviewer.md` + +**Placeholders:** +- `{WHAT_WAS_IMPLEMENTED}` - What you just built +- `{PLAN_OR_REQUIREMENTS}` - What it should do +- `{BASE_SHA}` - Starting commit +- `{HEAD_SHA}` - Ending commit +- `{DESCRIPTION}` - Brief summary + +**3. Act on feedback:** +- Fix Critical issues immediately +- Fix Important issues before proceeding +- Note Minor issues for later +- Push back if reviewer is wrong (with reasoning) + +## Example + +``` +[Just completed Task 2: Add verification function] + +You: Let me request code review before proceeding. + +BASE_SHA=$(git log --oneline | grep "Task 1" | head -1 | awk '{print $1}') +HEAD_SHA=$(git rev-parse HEAD) + +[Dispatch superpowers:code-reviewer subagent] + WHAT_WAS_IMPLEMENTED: Verification and repair functions for conversation index + PLAN_OR_REQUIREMENTS: Task 2 from docs/plans/deployment-plan.md + BASE_SHA: a7981ec + HEAD_SHA: 3df7661 + DESCRIPTION: Added verifyIndex() and repairIndex() with 4 issue types + +[Subagent returns]: + Strengths: Clean architecture, real tests + Issues: + Important: Missing progress indicators + Minor: Magic number (100) for reporting interval + Assessment: Ready to proceed + +You: [Fix progress indicators] +[Continue to Task 3] +``` + +## Integration with Workflows + +**Subagent-Driven Development:** +- Review after EACH task +- Catch issues before they compound +- Fix before moving to next task + +**Executing Plans:** +- Review after each batch (3 tasks) +- Get feedback, apply, continue + +**Ad-Hoc Development:** +- Review before merge +- Review when stuck + +## Red Flags + +**Never:** +- Skip review because "it's simple" +- Ignore Critical issues +- Proceed with unfixed Important issues +- Argue with valid technical feedback + +**If reviewer wrong:** +- Push back with technical reasoning +- Show code/tests that prove it works +- Request clarification + +See template at: requesting-code-review/code-reviewer.md diff --git a/account/admin/skills/superpowers-requesting-review/code-reviewer.md b/account/admin/skills/superpowers-requesting-review/code-reviewer.md new file mode 100644 index 0000000..3c427c9 --- /dev/null +++ b/account/admin/skills/superpowers-requesting-review/code-reviewer.md @@ -0,0 +1,146 @@ +# Code Review Agent + +You are reviewing code changes for production readiness. + +**Your task:** +1. Review {WHAT_WAS_IMPLEMENTED} +2. Compare against {PLAN_OR_REQUIREMENTS} +3. Check code quality, architecture, testing +4. Categorize issues by severity +5. Assess production readiness + +## What Was Implemented + +{DESCRIPTION} + +## Requirements/Plan + +{PLAN_REFERENCE} + +## Git Range to Review + +**Base:** {BASE_SHA} +**Head:** {HEAD_SHA} + +```bash +git diff --stat {BASE_SHA}..{HEAD_SHA} +git diff {BASE_SHA}..{HEAD_SHA} +``` + +## Review Checklist + +**Code Quality:** +- Clean separation of concerns? +- Proper error handling? +- Type safety (if applicable)? +- DRY principle followed? +- Edge cases handled? + +**Architecture:** +- Sound design decisions? +- Scalability considerations? +- Performance implications? +- Security concerns? + +**Testing:** +- Tests actually test logic (not mocks)? +- Edge cases covered? +- Integration tests where needed? +- All tests passing? + +**Requirements:** +- All plan requirements met? +- Implementation matches spec? +- No scope creep? +- Breaking changes documented? + +**Production Readiness:** +- Migration strategy (if schema changes)? +- Backward compatibility considered? +- Documentation complete? +- No obvious bugs? + +## Output Format + +### Strengths +[What's well done? Be specific.] + +### Issues + +#### Critical (Must Fix) +[Bugs, security issues, data loss risks, broken functionality] + +#### Important (Should Fix) +[Architecture problems, missing features, poor error handling, test gaps] + +#### Minor (Nice to Have) +[Code style, optimization opportunities, documentation improvements] + +**For each issue:** +- File:line reference +- What's wrong +- Why it matters +- How to fix (if not obvious) + +### Recommendations +[Improvements for code quality, architecture, or process] + +### Assessment + +**Ready to merge?** [Yes/No/With fixes] + +**Reasoning:** [Technical assessment in 1-2 sentences] + +## Critical Rules + +**DO:** +- Categorize by actual severity (not everything is Critical) +- Be specific (file:line, not vague) +- Explain WHY issues matter +- Acknowledge strengths +- Give clear verdict + +**DON'T:** +- Say "looks good" without checking +- Mark nitpicks as Critical +- Give feedback on code you didn't review +- Be vague ("improve error handling") +- Avoid giving a clear verdict + +## Example Output + +``` +### Strengths +- Clean database schema with proper migrations (db.ts:15-42) +- Comprehensive test coverage (18 tests, all edge cases) +- Good error handling with fallbacks (summarizer.ts:85-92) + +### Issues + +#### Important +1. **Missing help text in CLI wrapper** + - File: index-conversations:1-31 + - Issue: No --help flag, users won't discover --concurrency + - Fix: Add --help case with usage examples + +2. **Date validation missing** + - File: search.ts:25-27 + - Issue: Invalid dates silently return no results + - Fix: Validate ISO format, throw error with example + +#### Minor +1. **Progress indicators** + - File: indexer.ts:130 + - Issue: No "X of Y" counter for long operations + - Impact: Users don't know how long to wait + +### Recommendations +- Add progress reporting for user experience +- Consider config file for excluded projects (portability) + +### Assessment + +**Ready to merge: With fixes** + +**Reasoning:** Core implementation is solid with good architecture and tests. Important issues (help text, date validation) are easily fixed and don't affect core functionality. +``` diff --git a/account/admin/skills/superpowers-subagent-dev/.openakita-i18n.json b/account/admin/skills/superpowers-subagent-dev/.openakita-i18n.json new file mode 100644 index 0000000..d101104 --- /dev/null +++ b/account/admin/skills/superpowers-subagent-dev/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "子 Agent 驱动开发", + "description": "通过子 Agent 自主工作模式处理复杂开发任务,监督和审查子 Agent 产出" + } +} diff --git a/account/admin/skills/superpowers-subagent-dev/SKILL.md b/account/admin/skills/superpowers-subagent-dev/SKILL.md new file mode 100644 index 0000000..bf2e701 --- /dev/null +++ b/account/admin/skills/superpowers-subagent-dev/SKILL.md @@ -0,0 +1,242 @@ +--- +name: obra/superpowers@subagent-driven-development +description: Use when executing implementation plans with independent tasks in the current session +--- + +# Subagent-Driven Development + +Execute plan by dispatching fresh subagent per task, with two-stage review after each: spec compliance review first, then code quality review. + +**Core principle:** Fresh subagent per task + two-stage review (spec then quality) = high quality, fast iteration + +## When to Use + +```dot +digraph when_to_use { + "Have implementation plan?" [shape=diamond]; + "Tasks mostly independent?" [shape=diamond]; + "Stay in this session?" [shape=diamond]; + "subagent-driven-development" [shape=box]; + "executing-plans" [shape=box]; + "Manual execution or brainstorm first" [shape=box]; + + "Have implementation plan?" -> "Tasks mostly independent?" [label="yes"]; + "Have implementation plan?" -> "Manual execution or brainstorm first" [label="no"]; + "Tasks mostly independent?" -> "Stay in this session?" [label="yes"]; + "Tasks mostly independent?" -> "Manual execution or brainstorm first" [label="no - tightly coupled"]; + "Stay in this session?" -> "subagent-driven-development" [label="yes"]; + "Stay in this session?" -> "executing-plans" [label="no - parallel session"]; +} +``` + +**vs. Executing Plans (parallel session):** +- Same session (no context switch) +- Fresh subagent per task (no context pollution) +- Two-stage review after each task: spec compliance first, then code quality +- Faster iteration (no human-in-loop between tasks) + +## The Process + +```dot +digraph process { + rankdir=TB; + + subgraph cluster_per_task { + label="Per Task"; + "Dispatch implementer subagent (./implementer-prompt.md)" [shape=box]; + "Implementer subagent asks questions?" [shape=diamond]; + "Answer questions, provide context" [shape=box]; + "Implementer subagent implements, tests, commits, self-reviews" [shape=box]; + "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" [shape=box]; + "Spec reviewer subagent confirms code matches spec?" [shape=diamond]; + "Implementer subagent fixes spec gaps" [shape=box]; + "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [shape=box]; + "Code quality reviewer subagent approves?" [shape=diamond]; + "Implementer subagent fixes quality issues" [shape=box]; + "Mark task complete in TodoWrite" [shape=box]; + } + + "Read plan, extract all tasks with full text, note context, create TodoWrite" [shape=box]; + "More tasks remain?" [shape=diamond]; + "Dispatch final code reviewer subagent for entire implementation" [shape=box]; + "Use superpowers:finishing-a-development-branch" [shape=box style=filled fillcolor=lightgreen]; + + "Read plan, extract all tasks with full text, note context, create TodoWrite" -> "Dispatch implementer subagent (./implementer-prompt.md)"; + "Dispatch implementer subagent (./implementer-prompt.md)" -> "Implementer subagent asks questions?"; + "Implementer subagent asks questions?" -> "Answer questions, provide context" [label="yes"]; + "Answer questions, provide context" -> "Dispatch implementer subagent (./implementer-prompt.md)"; + "Implementer subagent asks questions?" -> "Implementer subagent implements, tests, commits, self-reviews" [label="no"]; + "Implementer subagent implements, tests, commits, self-reviews" -> "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)"; + "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" -> "Spec reviewer subagent confirms code matches spec?"; + "Spec reviewer subagent confirms code matches spec?" -> "Implementer subagent fixes spec gaps" [label="no"]; + "Implementer subagent fixes spec gaps" -> "Dispatch spec reviewer subagent (./spec-reviewer-prompt.md)" [label="re-review"]; + "Spec reviewer subagent confirms code matches spec?" -> "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [label="yes"]; + "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" -> "Code quality reviewer subagent approves?"; + "Code quality reviewer subagent approves?" -> "Implementer subagent fixes quality issues" [label="no"]; + "Implementer subagent fixes quality issues" -> "Dispatch code quality reviewer subagent (./code-quality-reviewer-prompt.md)" [label="re-review"]; + "Code quality reviewer subagent approves?" -> "Mark task complete in TodoWrite" [label="yes"]; + "Mark task complete in TodoWrite" -> "More tasks remain?"; + "More tasks remain?" -> "Dispatch implementer subagent (./implementer-prompt.md)" [label="yes"]; + "More tasks remain?" -> "Dispatch final code reviewer subagent for entire implementation" [label="no"]; + "Dispatch final code reviewer subagent for entire implementation" -> "Use superpowers:finishing-a-development-branch"; +} +``` + +## Prompt Templates + +- `./implementer-prompt.md` - Dispatch implementer subagent +- `./spec-reviewer-prompt.md` - Dispatch spec compliance reviewer subagent +- `./code-quality-reviewer-prompt.md` - Dispatch code quality reviewer subagent + +## Example Workflow + +``` +You: I'm using Subagent-Driven Development to execute this plan. + +[Read plan file once: docs/plans/feature-plan.md] +[Extract all 5 tasks with full text and context] +[Create TodoWrite with all tasks] + +Task 1: Hook installation script + +[Get Task 1 text and context (already extracted)] +[Dispatch implementation subagent with full task text + context] + +Implementer: "Before I begin - should the hook be installed at user or system level?" + +You: "User level (~/.config/superpowers/hooks/)" + +Implementer: "Got it. Implementing now..." +[Later] Implementer: + - Implemented install-hook command + - Added tests, 5/5 passing + - Self-review: Found I missed --force flag, added it + - Committed + +[Dispatch spec compliance reviewer] +Spec reviewer: ✅ Spec compliant - all requirements met, nothing extra + +[Get git SHAs, dispatch code quality reviewer] +Code reviewer: Strengths: Good test coverage, clean. Issues: None. Approved. + +[Mark Task 1 complete] + +Task 2: Recovery modes + +[Get Task 2 text and context (already extracted)] +[Dispatch implementation subagent with full task text + context] + +Implementer: [No questions, proceeds] +Implementer: + - Added verify/repair modes + - 8/8 tests passing + - Self-review: All good + - Committed + +[Dispatch spec compliance reviewer] +Spec reviewer: ❌ Issues: + - Missing: Progress reporting (spec says "report every 100 items") + - Extra: Added --json flag (not requested) + +[Implementer fixes issues] +Implementer: Removed --json flag, added progress reporting + +[Spec reviewer reviews again] +Spec reviewer: ✅ Spec compliant now + +[Dispatch code quality reviewer] +Code reviewer: Strengths: Solid. Issues (Important): Magic number (100) + +[Implementer fixes] +Implementer: Extracted PROGRESS_INTERVAL constant + +[Code reviewer reviews again] +Code reviewer: ✅ Approved + +[Mark Task 2 complete] + +... + +[After all tasks] +[Dispatch final code-reviewer] +Final reviewer: All requirements met, ready to merge + +Done! +``` + +## Advantages + +**vs. Manual execution:** +- Subagents follow TDD naturally +- Fresh context per task (no confusion) +- Parallel-safe (subagents don't interfere) +- Subagent can ask questions (before AND during work) + +**vs. Executing Plans:** +- Same session (no handoff) +- Continuous progress (no waiting) +- Review checkpoints automatic + +**Efficiency gains:** +- No file reading overhead (controller provides full text) +- Controller curates exactly what context is needed +- Subagent gets complete information upfront +- Questions surfaced before work begins (not after) + +**Quality gates:** +- Self-review catches issues before handoff +- Two-stage review: spec compliance, then code quality +- Review loops ensure fixes actually work +- Spec compliance prevents over/under-building +- Code quality ensures implementation is well-built + +**Cost:** +- More subagent invocations (implementer + 2 reviewers per task) +- Controller does more prep work (extracting all tasks upfront) +- Review loops add iterations +- But catches issues early (cheaper than debugging later) + +## Red Flags + +**Never:** +- Start implementation on main/master branch without explicit user consent +- Skip reviews (spec compliance OR code quality) +- Proceed with unfixed issues +- Dispatch multiple implementation subagents in parallel (conflicts) +- Make subagent read plan file (provide full text instead) +- Skip scene-setting context (subagent needs to understand where task fits) +- Ignore subagent questions (answer before letting them proceed) +- Accept "close enough" on spec compliance (spec reviewer found issues = not done) +- Skip review loops (reviewer found issues = implementer fixes = review again) +- Let implementer self-review replace actual review (both are needed) +- **Start code quality review before spec compliance is ✅** (wrong order) +- Move to next task while either review has open issues + +**If subagent asks questions:** +- Answer clearly and completely +- Provide additional context if needed +- Don't rush them into implementation + +**If reviewer finds issues:** +- Implementer (same subagent) fixes them +- Reviewer reviews again +- Repeat until approved +- Don't skip the re-review + +**If subagent fails task:** +- Dispatch fix subagent with specific instructions +- Don't try to fix manually (context pollution) + +## Integration + +**Required workflow skills:** +- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting +- **superpowers:writing-plans** - Creates the plan this skill executes +- **superpowers:requesting-code-review** - Code review template for reviewer subagents +- **superpowers:finishing-a-development-branch** - Complete development after all tasks + +**Subagents should use:** +- **superpowers:test-driven-development** - Subagents follow TDD for each task + +**Alternative workflow:** +- **superpowers:executing-plans** - Use for parallel session instead of same-session execution diff --git a/account/admin/skills/superpowers-subagent-dev/code-quality-reviewer-prompt.md b/account/admin/skills/superpowers-subagent-dev/code-quality-reviewer-prompt.md new file mode 100644 index 0000000..d029ea2 --- /dev/null +++ b/account/admin/skills/superpowers-subagent-dev/code-quality-reviewer-prompt.md @@ -0,0 +1,20 @@ +# Code Quality Reviewer Prompt Template + +Use this template when dispatching a code quality reviewer subagent. + +**Purpose:** Verify implementation is well-built (clean, tested, maintainable) + +**Only dispatch after spec compliance review passes.** + +``` +Task tool (superpowers:code-reviewer): + Use template at requesting-code-review/code-reviewer.md + + WHAT_WAS_IMPLEMENTED: [from implementer's report] + PLAN_OR_REQUIREMENTS: Task N from [plan-file] + BASE_SHA: [commit before task] + HEAD_SHA: [current commit] + DESCRIPTION: [task summary] +``` + +**Code reviewer returns:** Strengths, Issues (Critical/Important/Minor), Assessment diff --git a/account/admin/skills/superpowers-subagent-dev/implementer-prompt.md b/account/admin/skills/superpowers-subagent-dev/implementer-prompt.md new file mode 100644 index 0000000..db5404b --- /dev/null +++ b/account/admin/skills/superpowers-subagent-dev/implementer-prompt.md @@ -0,0 +1,78 @@ +# Implementer Subagent Prompt Template + +Use this template when dispatching an implementer subagent. + +``` +Task tool (general-purpose): + description: "Implement Task N: [task name]" + prompt: | + You are implementing Task N: [task name] + + ## Task Description + + [FULL TEXT of task from plan - paste it here, don't make subagent read file] + + ## Context + + [Scene-setting: where this fits, dependencies, architectural context] + + ## Before You Begin + + If you have questions about: + - The requirements or acceptance criteria + - The approach or implementation strategy + - Dependencies or assumptions + - Anything unclear in the task description + + **Ask them now.** Raise any concerns before starting work. + + ## Your Job + + Once you're clear on requirements: + 1. Implement exactly what the task specifies + 2. Write tests (following TDD if task says to) + 3. Verify implementation works + 4. Commit your work + 5. Self-review (see below) + 6. Report back + + Work from: [directory] + + **While you work:** If you encounter something unexpected or unclear, **ask questions**. + It's always OK to pause and clarify. Don't guess or make assumptions. + + ## Before Reporting Back: Self-Review + + Review your work with fresh eyes. Ask yourself: + + **Completeness:** + - Did I fully implement everything in the spec? + - Did I miss any requirements? + - Are there edge cases I didn't handle? + + **Quality:** + - Is this my best work? + - Are names clear and accurate (match what things do, not how they work)? + - Is the code clean and maintainable? + + **Discipline:** + - Did I avoid overbuilding (YAGNI)? + - Did I only build what was requested? + - Did I follow existing patterns in the codebase? + + **Testing:** + - Do tests actually verify behavior (not just mock behavior)? + - Did I follow TDD if required? + - Are tests comprehensive? + + If you find issues during self-review, fix them now before reporting. + + ## Report Format + + When done, report: + - What you implemented + - What you tested and test results + - Files changed + - Self-review findings (if any) + - Any issues or concerns +``` diff --git a/account/admin/skills/superpowers-subagent-dev/spec-reviewer-prompt.md b/account/admin/skills/superpowers-subagent-dev/spec-reviewer-prompt.md new file mode 100644 index 0000000..ab5ddb8 --- /dev/null +++ b/account/admin/skills/superpowers-subagent-dev/spec-reviewer-prompt.md @@ -0,0 +1,61 @@ +# Spec Compliance Reviewer Prompt Template + +Use this template when dispatching a spec compliance reviewer subagent. + +**Purpose:** Verify implementer built what was requested (nothing more, nothing less) + +``` +Task tool (general-purpose): + description: "Review spec compliance for Task N" + prompt: | + You are reviewing whether an implementation matches its specification. + + ## What Was Requested + + [FULL TEXT of task requirements] + + ## What Implementer Claims They Built + + [From implementer's report] + + ## CRITICAL: Do Not Trust the Report + + The implementer finished suspiciously quickly. Their report may be incomplete, + inaccurate, or optimistic. You MUST verify everything independently. + + **DO NOT:** + - Take their word for what they implemented + - Trust their claims about completeness + - Accept their interpretation of requirements + + **DO:** + - Read the actual code they wrote + - Compare actual implementation to requirements line by line + - Check for missing pieces they claimed to implement + - Look for extra features they didn't mention + + ## Your Job + + Read the implementation code and verify: + + **Missing requirements:** + - Did they implement everything that was requested? + - Are there requirements they skipped or missed? + - Did they claim something works but didn't actually implement it? + + **Extra/unneeded work:** + - Did they build things that weren't requested? + - Did they over-engineer or add unnecessary features? + - Did they add "nice to haves" that weren't in spec? + + **Misunderstandings:** + - Did they interpret requirements differently than intended? + - Did they solve the wrong problem? + - Did they implement the right feature but wrong way? + + **Verify by reading code, not by trusting report.** + + Report: + - ✅ Spec compliant (if everything matches after code inspection) + - ❌ Issues found: [list specifically what's missing or extra, with file:line references] +``` diff --git a/account/admin/skills/superpowers-tdd/.openakita-i18n.json b/account/admin/skills/superpowers-tdd/.openakita-i18n.json new file mode 100644 index 0000000..06a99fc --- /dev/null +++ b/account/admin/skills/superpowers-tdd/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "测试驱动开发", + "description": "Red-Green-Refactor 工作流:先写失败测试,再写最小实现代码,最后重构。确保每行代码都有测试覆盖" + } +} diff --git a/account/admin/skills/superpowers-tdd/SKILL.md b/account/admin/skills/superpowers-tdd/SKILL.md new file mode 100644 index 0000000..e4b94ce --- /dev/null +++ b/account/admin/skills/superpowers-tdd/SKILL.md @@ -0,0 +1,371 @@ +--- +name: obra/superpowers@test-driven-development +description: Use when implementing any feature or bugfix, before writing implementation code +--- + +# Test-Driven Development (TDD) + +## Overview + +Write the test first. Watch it fail. Write minimal code to pass. + +**Core principle:** If you didn't watch the test fail, you don't know if it tests the right thing. + +**Violating the letter of the rules is violating the spirit of the rules.** + +## When to Use + +**Always:** +- New features +- Bug fixes +- Refactoring +- Behavior changes + +**Exceptions (ask your human partner):** +- Throwaway prototypes +- Generated code +- Configuration files + +Thinking "skip TDD just this once"? Stop. That's rationalization. + +## The Iron Law + +``` +NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST +``` + +Write code before the test? Delete it. Start over. + +**No exceptions:** +- Don't keep it as "reference" +- Don't "adapt" it while writing tests +- Don't look at it +- Delete means delete + +Implement fresh from tests. Period. + +## Red-Green-Refactor + +```dot +digraph tdd_cycle { + rankdir=LR; + red [label="RED\nWrite failing test", shape=box, style=filled, fillcolor="#ffcccc"]; + verify_red [label="Verify fails\ncorrectly", shape=diamond]; + green [label="GREEN\nMinimal code", shape=box, style=filled, fillcolor="#ccffcc"]; + verify_green [label="Verify passes\nAll green", shape=diamond]; + refactor [label="REFACTOR\nClean up", shape=box, style=filled, fillcolor="#ccccff"]; + next [label="Next", shape=ellipse]; + + red -> verify_red; + verify_red -> green [label="yes"]; + verify_red -> red [label="wrong\nfailure"]; + green -> verify_green; + verify_green -> refactor [label="yes"]; + verify_green -> green [label="no"]; + refactor -> verify_green [label="stay\ngreen"]; + verify_green -> next; + next -> red; +} +``` + +### RED - Write Failing Test + +Write one minimal test showing what should happen. + +<Good> +```typescript +test('retries failed operations 3 times', async () => { + let attempts = 0; + const operation = () => { + attempts++; + if (attempts < 3) throw new Error('fail'); + return 'success'; + }; + + const result = await retryOperation(operation); + + expect(result).toBe('success'); + expect(attempts).toBe(3); +}); +``` +Clear name, tests real behavior, one thing +</Good> + +<Bad> +```typescript +test('retry works', async () => { + const mock = jest.fn() + .mockRejectedValueOnce(new Error()) + .mockRejectedValueOnce(new Error()) + .mockResolvedValueOnce('success'); + await retryOperation(mock); + expect(mock).toHaveBeenCalledTimes(3); +}); +``` +Vague name, tests mock not code +</Bad> + +**Requirements:** +- One behavior +- Clear name +- Real code (no mocks unless unavoidable) + +### Verify RED - Watch It Fail + +**MANDATORY. Never skip.** + +```bash +npm test path/to/test.test.ts +``` + +Confirm: +- Test fails (not errors) +- Failure message is expected +- Fails because feature missing (not typos) + +**Test passes?** You're testing existing behavior. Fix test. + +**Test errors?** Fix error, re-run until it fails correctly. + +### GREEN - Minimal Code + +Write simplest code to pass the test. + +<Good> +```typescript +async function retryOperation<T>(fn: () => Promise<T>): Promise<T> { + for (let i = 0; i < 3; i++) { + try { + return await fn(); + } catch (e) { + if (i === 2) throw e; + } + } + throw new Error('unreachable'); +} +``` +Just enough to pass +</Good> + +<Bad> +```typescript +async function retryOperation<T>( + fn: () => Promise<T>, + options?: { + maxRetries?: number; + backoff?: 'linear' | 'exponential'; + onRetry?: (attempt: number) => void; + } +): Promise<T> { + // YAGNI +} +``` +Over-engineered +</Bad> + +Don't add features, refactor other code, or "improve" beyond the test. + +### Verify GREEN - Watch It Pass + +**MANDATORY.** + +```bash +npm test path/to/test.test.ts +``` + +Confirm: +- Test passes +- Other tests still pass +- Output pristine (no errors, warnings) + +**Test fails?** Fix code, not test. + +**Other tests fail?** Fix now. + +### REFACTOR - Clean Up + +After green only: +- Remove duplication +- Improve names +- Extract helpers + +Keep tests green. Don't add behavior. + +### Repeat + +Next failing test for next feature. + +## Good Tests + +| Quality | Good | Bad | +|---------|------|-----| +| **Minimal** | One thing. "and" in name? Split it. | `test('validates email and domain and whitespace')` | +| **Clear** | Name describes behavior | `test('test1')` | +| **Shows intent** | Demonstrates desired API | Obscures what code should do | + +## Why Order Matters + +**"I'll write tests after to verify it works"** + +Tests written after code pass immediately. Passing immediately proves nothing: +- Might test wrong thing +- Might test implementation, not behavior +- Might miss edge cases you forgot +- You never saw it catch the bug + +Test-first forces you to see the test fail, proving it actually tests something. + +**"I already manually tested all the edge cases"** + +Manual testing is ad-hoc. You think you tested everything but: +- No record of what you tested +- Can't re-run when code changes +- Easy to forget cases under pressure +- "It worked when I tried it" ≠ comprehensive + +Automated tests are systematic. They run the same way every time. + +**"Deleting X hours of work is wasteful"** + +Sunk cost fallacy. The time is already gone. Your choice now: +- Delete and rewrite with TDD (X more hours, high confidence) +- Keep it and add tests after (30 min, low confidence, likely bugs) + +The "waste" is keeping code you can't trust. Working code without real tests is technical debt. + +**"TDD is dogmatic, being pragmatic means adapting"** + +TDD IS pragmatic: +- Finds bugs before commit (faster than debugging after) +- Prevents regressions (tests catch breaks immediately) +- Documents behavior (tests show how to use code) +- Enables refactoring (change freely, tests catch breaks) + +"Pragmatic" shortcuts = debugging in production = slower. + +**"Tests after achieve the same goals - it's spirit not ritual"** + +No. Tests-after answer "What does this do?" Tests-first answer "What should this do?" + +Tests-after are biased by your implementation. You test what you built, not what's required. You verify remembered edge cases, not discovered ones. + +Tests-first force edge case discovery before implementing. Tests-after verify you remembered everything (you didn't). + +30 minutes of tests after ≠ TDD. You get coverage, lose proof tests work. + +## Common Rationalizations + +| Excuse | Reality | +|--------|---------| +| "Too simple to test" | Simple code breaks. Test takes 30 seconds. | +| "I'll test after" | Tests passing immediately prove nothing. | +| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" | +| "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. | +| "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. | +| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. | +| "Need to explore first" | Fine. Throw away exploration, start with TDD. | +| "Test hard = design unclear" | Listen to test. Hard to test = hard to use. | +| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. | +| "Manual test faster" | Manual doesn't prove edge cases. You'll re-test every change. | +| "Existing code has no tests" | You're improving it. Add tests for existing code. | + +## Red Flags - STOP and Start Over + +- Code before test +- Test after implementation +- Test passes immediately +- Can't explain why test failed +- Tests added "later" +- Rationalizing "just this once" +- "I already manually tested it" +- "Tests after achieve the same purpose" +- "It's about spirit not ritual" +- "Keep as reference" or "adapt existing code" +- "Already spent X hours, deleting is wasteful" +- "TDD is dogmatic, I'm being pragmatic" +- "This is different because..." + +**All of these mean: Delete code. Start over with TDD.** + +## Example: Bug Fix + +**Bug:** Empty email accepted + +**RED** +```typescript +test('rejects empty email', async () => { + const result = await submitForm({ email: '' }); + expect(result.error).toBe('Email required'); +}); +``` + +**Verify RED** +```bash +$ npm test +FAIL: expected 'Email required', got undefined +``` + +**GREEN** +```typescript +function submitForm(data: FormData) { + if (!data.email?.trim()) { + return { error: 'Email required' }; + } + // ... +} +``` + +**Verify GREEN** +```bash +$ npm test +PASS +``` + +**REFACTOR** +Extract validation for multiple fields if needed. + +## Verification Checklist + +Before marking work complete: + +- [ ] Every new function/method has a test +- [ ] Watched each test fail before implementing +- [ ] Each test failed for expected reason (feature missing, not typo) +- [ ] Wrote minimal code to pass each test +- [ ] All tests pass +- [ ] Output pristine (no errors, warnings) +- [ ] Tests use real code (mocks only if unavoidable) +- [ ] Edge cases and errors covered + +Can't check all boxes? You skipped TDD. Start over. + +## When Stuck + +| Problem | Solution | +|---------|----------| +| Don't know how to test | Write wished-for API. Write assertion first. Ask your human partner. | +| Test too complicated | Design too complicated. Simplify interface. | +| Must mock everything | Code too coupled. Use dependency injection. | +| Test setup huge | Extract helpers. Still complex? Simplify design. | + +## Debugging Integration + +Bug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression. + +Never fix bugs without a test. + +## Testing Anti-Patterns + +When adding mocks or test utilities, read @testing-anti-patterns.md to avoid common pitfalls: +- Testing mock behavior instead of real behavior +- Adding test-only methods to production classes +- Mocking without understanding dependencies + +## Final Rule + +``` +Production code → test exists and failed first +Otherwise → not TDD +``` + +No exceptions without your human partner's permission. diff --git a/account/admin/skills/superpowers-verification/.openakita-i18n.json b/account/admin/skills/superpowers-verification/.openakita-i18n.json new file mode 100644 index 0000000..0667528 --- /dev/null +++ b/account/admin/skills/superpowers-verification/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "完成前验证", + "description": "在声明任务完成前必须运行验证命令并确认输出,用证据支持结论,杜绝假完成" + } +} diff --git a/account/admin/skills/superpowers-verification/SKILL.md b/account/admin/skills/superpowers-verification/SKILL.md new file mode 100644 index 0000000..06358cf --- /dev/null +++ b/account/admin/skills/superpowers-verification/SKILL.md @@ -0,0 +1,139 @@ +--- +name: obra/superpowers@verification-before-completion +description: Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always +--- + +# Verification Before Completion + +## Overview + +Claiming work is complete without verification is dishonesty, not efficiency. + +**Core principle:** Evidence before claims, always. + +**Violating the letter of this rule is violating the spirit of this rule.** + +## The Iron Law + +``` +NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE +``` + +If you haven't run the verification command in this message, you cannot claim it passes. + +## The Gate Function + +``` +BEFORE claiming any status or expressing satisfaction: + +1. IDENTIFY: What command proves this claim? +2. RUN: Execute the FULL command (fresh, complete) +3. READ: Full output, check exit code, count failures +4. VERIFY: Does output confirm the claim? + - If NO: State actual status with evidence + - If YES: State claim WITH evidence +5. ONLY THEN: Make the claim + +Skip any step = lying, not verifying +``` + +## Common Failures + +| Claim | Requires | Not Sufficient | +|-------|----------|----------------| +| Tests pass | Test command output: 0 failures | Previous run, "should pass" | +| Linter clean | Linter output: 0 errors | Partial check, extrapolation | +| Build succeeds | Build command: exit 0 | Linter passing, logs look good | +| Bug fixed | Test original symptom: passes | Code changed, assumed fixed | +| Regression test works | Red-green cycle verified | Test passes once | +| Agent completed | VCS diff shows changes | Agent reports "success" | +| Requirements met | Line-by-line checklist | Tests passing | + +## Red Flags - STOP + +- Using "should", "probably", "seems to" +- Expressing satisfaction before verification ("Great!", "Perfect!", "Done!", etc.) +- About to commit/push/PR without verification +- Trusting agent success reports +- Relying on partial verification +- Thinking "just this once" +- Tired and wanting work over +- **ANY wording implying success without having run verification** + +## Rationalization Prevention + +| Excuse | Reality | +|--------|---------| +| "Should work now" | RUN the verification | +| "I'm confident" | Confidence ≠ evidence | +| "Just this once" | No exceptions | +| "Linter passed" | Linter ≠ compiler | +| "Agent said success" | Verify independently | +| "I'm tired" | Exhaustion ≠ excuse | +| "Partial check is enough" | Partial proves nothing | +| "Different words so rule doesn't apply" | Spirit over letter | + +## Key Patterns + +**Tests:** +``` +✅ [Run test command] [See: 34/34 pass] "All tests pass" +❌ "Should pass now" / "Looks correct" +``` + +**Regression tests (TDD Red-Green):** +``` +✅ Write → Run (pass) → Revert fix → Run (MUST FAIL) → Restore → Run (pass) +❌ "I've written a regression test" (without red-green verification) +``` + +**Build:** +``` +✅ [Run build] [See: exit 0] "Build passes" +❌ "Linter passed" (linter doesn't check compilation) +``` + +**Requirements:** +``` +✅ Re-read plan → Create checklist → Verify each → Report gaps or completion +❌ "Tests pass, phase complete" +``` + +**Agent delegation:** +``` +✅ Agent reports success → Check VCS diff → Verify changes → Report actual state +❌ Trust agent report +``` + +## Why This Matters + +From 24 failure memories: +- your human partner said "I don't believe you" - trust broken +- Undefined functions shipped - would crash +- Missing requirements shipped - incomplete features +- Time wasted on false completion → redirect → rework +- Violates: "Honesty is a core value. If you lie, you'll be replaced." + +## When To Apply + +**ALWAYS before:** +- ANY variation of success/completion claims +- ANY expression of satisfaction +- ANY positive statement about work state +- Committing, PR creation, task completion +- Moving to next task +- Delegating to agents + +**Rule applies to:** +- Exact phrases +- Paraphrases and synonyms +- Implications of success +- ANY communication suggesting completion/correctness + +## The Bottom Line + +**No shortcuts for verification.** + +Run the command. Read the output. THEN claim the result. + +This is non-negotiable. diff --git a/account/admin/skills/superpowers-workflow/.openakita-i18n.json b/account/admin/skills/superpowers-workflow/.openakita-i18n.json new file mode 100644 index 0000000..fcdee3f --- /dev/null +++ b/account/admin/skills/superpowers-workflow/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Superpowers 工作流", + "description": "Superpowers 开发方法论入口:在执行任何任务前检查并应用合适的技能" + } +} diff --git a/account/admin/skills/superpowers-workflow/SKILL.md b/account/admin/skills/superpowers-workflow/SKILL.md new file mode 100644 index 0000000..be3fd94 --- /dev/null +++ b/account/admin/skills/superpowers-workflow/SKILL.md @@ -0,0 +1,95 @@ +--- +name: obra/superpowers@using-superpowers +description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions +--- + +<EXTREMELY-IMPORTANT> +If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill. + +IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT. + +This is not negotiable. This is not optional. You cannot rationalize your way out of this. +</EXTREMELY-IMPORTANT> + +## How to Access Skills + +**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files. + +**In other environments:** Check your platform's documentation for how skills are loaded. + +# Using Skills + +## The Rule + +**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it. + +```dot +digraph skill_flow { + "User message received" [shape=doublecircle]; + "About to EnterPlanMode?" [shape=doublecircle]; + "Already brainstormed?" [shape=diamond]; + "Invoke brainstorming skill" [shape=box]; + "Might any skill apply?" [shape=diamond]; + "Invoke Skill tool" [shape=box]; + "Announce: 'Using [skill] to [purpose]'" [shape=box]; + "Has checklist?" [shape=diamond]; + "Create TodoWrite todo per item" [shape=box]; + "Follow skill exactly" [shape=box]; + "Respond (including clarifications)" [shape=doublecircle]; + + "About to EnterPlanMode?" -> "Already brainstormed?"; + "Already brainstormed?" -> "Invoke brainstorming skill" [label="no"]; + "Already brainstormed?" -> "Might any skill apply?" [label="yes"]; + "Invoke brainstorming skill" -> "Might any skill apply?"; + + "User message received" -> "Might any skill apply?"; + "Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"]; + "Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"]; + "Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'"; + "Announce: 'Using [skill] to [purpose]'" -> "Has checklist?"; + "Has checklist?" -> "Create TodoWrite todo per item" [label="yes"]; + "Has checklist?" -> "Follow skill exactly" [label="no"]; + "Create TodoWrite todo per item" -> "Follow skill exactly"; +} +``` + +## Red Flags + +These thoughts mean STOP—you're rationalizing: + +| Thought | Reality | +|---------|---------| +| "This is just a simple question" | Questions are tasks. Check for skills. | +| "I need more context first" | Skill check comes BEFORE clarifying questions. | +| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. | +| "I can check git/files quickly" | Files lack conversation context. Check for skills. | +| "Let me gather information first" | Skills tell you HOW to gather information. | +| "This doesn't need a formal skill" | If a skill exists, use it. | +| "I remember this skill" | Skills evolve. Read current version. | +| "This doesn't count as a task" | Action = task. Check for skills. | +| "The skill is overkill" | Simple things become complex. Use it. | +| "I'll just do this one thing first" | Check BEFORE doing anything. | +| "This feels productive" | Undisciplined action wastes time. Skills prevent this. | +| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. | + +## Skill Priority + +When multiple skills could apply, use this order: + +1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task +2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution + +"Let's build X" → brainstorming first, then implementation skills. +"Fix this bug" → debugging first, then domain-specific skills. + +## Skill Types + +**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline. + +**Flexible** (patterns): Adapt principles to context. + +The skill itself tells you which. + +## User Instructions + +Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows. diff --git a/account/admin/skills/superpowers-writing-plans/.openakita-i18n.json b/account/admin/skills/superpowers-writing-plans/.openakita-i18n.json new file mode 100644 index 0000000..2f44a2e --- /dev/null +++ b/account/admin/skills/superpowers-writing-plans/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "编写实施计划", + "description": "将设计文档转化为可执行的分步实施计划,每步2-5分钟,可独立验证" + } +} diff --git a/account/admin/skills/superpowers-writing-plans/SKILL.md b/account/admin/skills/superpowers-writing-plans/SKILL.md new file mode 100644 index 0000000..98249c3 --- /dev/null +++ b/account/admin/skills/superpowers-writing-plans/SKILL.md @@ -0,0 +1,116 @@ +--- +name: obra/superpowers@writing-plans +description: Use when you have a spec or requirements for a multi-step task, before touching code +--- + +# Writing Plans + +## Overview + +Write comprehensive implementation plans assuming the engineer has zero context for our codebase and questionable taste. Document everything they need to know: which files to touch for each task, code, testing, docs they might need to check, how to test it. Give them the whole plan as bite-sized tasks. DRY. YAGNI. TDD. Frequent commits. + +Assume they are a skilled developer, but know almost nothing about our toolset or problem domain. Assume they don't know good test design very well. + +**Announce at start:** "I'm using the writing-plans skill to create the implementation plan." + +**Context:** This should be run in a dedicated worktree (created by brainstorming skill). + +**Save plans to:** `docs/plans/YYYY-MM-DD-<feature-name>.md` + +## Bite-Sized Task Granularity + +**Each step is one action (2-5 minutes):** +- "Write the failing test" - step +- "Run it to make sure it fails" - step +- "Implement the minimal code to make the test pass" - step +- "Run the tests and make sure they pass" - step +- "Commit" - step + +## Plan Document Header + +**Every plan MUST start with this header:** + +```markdown +# [Feature Name] Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** [One sentence describing what this builds] + +**Architecture:** [2-3 sentences about approach] + +**Tech Stack:** [Key technologies/libraries] + +--- +``` + +## Task Structure + +````markdown +### Task N: [Component Name] + +**Files:** +- Create: `exact/path/to/file.py` +- Modify: `exact/path/to/existing.py:123-145` +- Test: `tests/exact/path/to/test.py` + +**Step 1: Write the failing test** + +```python +def test_specific_behavior(): + result = function(input) + assert result == expected +``` + +**Step 2: Run test to verify it fails** + +Run: `pytest tests/path/test.py::test_name -v` +Expected: FAIL with "function not defined" + +**Step 3: Write minimal implementation** + +```python +def function(input): + return expected +``` + +**Step 4: Run test to verify it passes** + +Run: `pytest tests/path/test.py::test_name -v` +Expected: PASS + +**Step 5: Commit** + +```bash +git add tests/path/test.py src/path/file.py +git commit -m "feat: add specific feature" +``` +```` + +## Remember +- Exact file paths always +- Complete code in plan (not "add validation") +- Exact commands with expected output +- Reference relevant skills with @ syntax +- DRY, YAGNI, TDD, frequent commits + +## Execution Handoff + +After saving the plan, offer execution choice: + +**"Plan complete and saved to `docs/plans/<filename>.md`. Two execution options:** + +**1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration + +**2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints + +**Which approach?"** + +**If Subagent-Driven chosen:** +- **REQUIRED SUB-SKILL:** Use superpowers:subagent-driven-development +- Stay in this session +- Fresh subagent per task + code review + +**If Parallel Session chosen:** +- Guide them to open new session in worktree +- **REQUIRED SUB-SKILL:** New session uses superpowers:executing-plans diff --git a/account/admin/skills/superpowers-writing-skills/.openakita-i18n.json b/account/admin/skills/superpowers-writing-skills/.openakita-i18n.json new file mode 100644 index 0000000..3bdc264 --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "编写技能文件", + "description": "创建和维护 SKILL.md 技能定义文件的最佳实践指南" + } +} diff --git a/account/admin/skills/superpowers-writing-skills/SKILL.md b/account/admin/skills/superpowers-writing-skills/SKILL.md new file mode 100644 index 0000000..ec934b2 --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/SKILL.md @@ -0,0 +1,655 @@ +--- +name: obra/superpowers@writing-skills +description: Use when creating new skills, editing existing skills, or verifying skills work before deployment +--- + +# Writing Skills + +## Overview + +**Writing skills IS Test-Driven Development applied to process documentation.** + +**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.agents/skills/` for Codex)** + +You write test cases (pressure scenarios with subagents), watch them fail (baseline behavior), write the skill (documentation), watch tests pass (agents comply), and refactor (close loopholes). + +**Core principle:** If you didn't watch an agent fail without the skill, you don't know if the skill teaches the right thing. + +**REQUIRED BACKGROUND:** You MUST understand superpowers:test-driven-development before using this skill. That skill defines the fundamental RED-GREEN-REFACTOR cycle. This skill adapts TDD to documentation. + +**Official guidance:** For Anthropic's official skill authoring best practices, see anthropic-best-practices.md. This document provides additional patterns and guidelines that complement the TDD-focused approach in this skill. + +## What is a Skill? + +A **skill** is a reference guide for proven techniques, patterns, or tools. Skills help future Claude instances find and apply effective approaches. + +**Skills are:** Reusable techniques, patterns, tools, reference guides + +**Skills are NOT:** Narratives about how you solved a problem once + +## TDD Mapping for Skills + +| TDD Concept | Skill Creation | +|-------------|----------------| +| **Test case** | Pressure scenario with subagent | +| **Production code** | Skill document (SKILL.md) | +| **Test fails (RED)** | Agent violates rule without skill (baseline) | +| **Test passes (GREEN)** | Agent complies with skill present | +| **Refactor** | Close loopholes while maintaining compliance | +| **Write test first** | Run baseline scenario BEFORE writing skill | +| **Watch it fail** | Document exact rationalizations agent uses | +| **Minimal code** | Write skill addressing those specific violations | +| **Watch it pass** | Verify agent now complies | +| **Refactor cycle** | Find new rationalizations → plug → re-verify | + +The entire skill creation process follows RED-GREEN-REFACTOR. + +## When to Create a Skill + +**Create when:** +- Technique wasn't intuitively obvious to you +- You'd reference this again across projects +- Pattern applies broadly (not project-specific) +- Others would benefit + +**Don't create for:** +- One-off solutions +- Standard practices well-documented elsewhere +- Project-specific conventions (put in CLAUDE.md) +- Mechanical constraints (if it's enforceable with regex/validation, automate it—save documentation for judgment calls) + +## Skill Types + +### Technique +Concrete method with steps to follow (condition-based-waiting, root-cause-tracing) + +### Pattern +Way of thinking about problems (flatten-with-flags, test-invariants) + +### Reference +API docs, syntax guides, tool documentation (office docs) + +## Directory Structure + + +``` +skills/ + skill-name/ + SKILL.md # Main reference (required) + supporting-file.* # Only if needed +``` + +**Flat namespace** - all skills in one searchable namespace + +**Separate files for:** +1. **Heavy reference** (100+ lines) - API docs, comprehensive syntax +2. **Reusable tools** - Scripts, utilities, templates + +**Keep inline:** +- Principles and concepts +- Code patterns (< 50 lines) +- Everything else + +## SKILL.md Structure + +**Frontmatter (YAML):** +- Only two fields supported: `name` and `description` +- Max 1024 characters total +- `name`: Use letters, numbers, and hyphens only (no parentheses, special chars) +- `description`: Third-person, describes ONLY when to use (NOT what it does) + - Start with "Use when..." to focus on triggering conditions + - Include specific symptoms, situations, and contexts + - **NEVER summarize the skill's process or workflow** (see CSO section for why) + - Keep under 500 characters if possible + +```markdown +--- +name: Skill-Name-With-Hyphens +description: Use when [specific triggering conditions and symptoms] +--- + +# Skill Name + +## Overview +What is this? Core principle in 1-2 sentences. + +## When to Use +[Small inline flowchart IF decision non-obvious] + +Bullet list with SYMPTOMS and use cases +When NOT to use + +## Core Pattern (for techniques/patterns) +Before/after code comparison + +## Quick Reference +Table or bullets for scanning common operations + +## Implementation +Inline code for simple patterns +Link to file for heavy reference or reusable tools + +## Common Mistakes +What goes wrong + fixes + +## Real-World Impact (optional) +Concrete results +``` + + +## Claude Search Optimization (CSO) + +**Critical for discovery:** Future Claude needs to FIND your skill + +### 1. Rich Description Field + +**Purpose:** Claude reads description to decide which skills to load for a given task. Make it answer: "Should I read this skill right now?" + +**Format:** Start with "Use when..." to focus on triggering conditions + +**CRITICAL: Description = When to Use, NOT What the Skill Does** + +The description should ONLY describe triggering conditions. Do NOT summarize the skill's process or workflow in the description. + +**Why this matters:** Testing revealed that when a description summarizes the skill's workflow, Claude may follow the description instead of reading the full skill content. A description saying "code review between tasks" caused Claude to do ONE review, even though the skill's flowchart clearly showed TWO reviews (spec compliance then code quality). + +When the description was changed to just "Use when executing implementation plans with independent tasks" (no workflow summary), Claude correctly read the flowchart and followed the two-stage review process. + +**The trap:** Descriptions that summarize workflow create a shortcut Claude will take. The skill body becomes documentation Claude skips. + +```yaml +# ❌ BAD: Summarizes workflow - Claude may follow this instead of reading skill +description: Use when executing plans - dispatches subagent per task with code review between tasks + +# ❌ BAD: Too much process detail +description: Use for TDD - write test first, watch it fail, write minimal code, refactor + +# ✅ GOOD: Just triggering conditions, no workflow summary +description: Use when executing implementation plans with independent tasks in the current session + +# ✅ GOOD: Triggering conditions only +description: Use when implementing any feature or bugfix, before writing implementation code +``` + +**Content:** +- Use concrete triggers, symptoms, and situations that signal this skill applies +- Describe the *problem* (race conditions, inconsistent behavior) not *language-specific symptoms* (setTimeout, sleep) +- Keep triggers technology-agnostic unless the skill itself is technology-specific +- If skill is technology-specific, make that explicit in the trigger +- Write in third person (injected into system prompt) +- **NEVER summarize the skill's process or workflow** + +```yaml +# ❌ BAD: Too abstract, vague, doesn't include when to use +description: For async testing + +# ❌ BAD: First person +description: I can help you with async tests when they're flaky + +# ❌ BAD: Mentions technology but skill isn't specific to it +description: Use when tests use setTimeout/sleep and are flaky + +# ✅ GOOD: Starts with "Use when", describes problem, no workflow +description: Use when tests have race conditions, timing dependencies, or pass/fail inconsistently + +# ✅ GOOD: Technology-specific skill with explicit trigger +description: Use when using React Router and handling authentication redirects +``` + +### 2. Keyword Coverage + +Use words Claude would search for: +- Error messages: "Hook timed out", "ENOTEMPTY", "race condition" +- Symptoms: "flaky", "hanging", "zombie", "pollution" +- Synonyms: "timeout/hang/freeze", "cleanup/teardown/afterEach" +- Tools: Actual commands, library names, file types + +### 3. Descriptive Naming + +**Use active voice, verb-first:** +- ✅ `creating-skills` not `skill-creation` +- ✅ `condition-based-waiting` not `async-test-helpers` + +### 4. Token Efficiency (Critical) + +**Problem:** getting-started and frequently-referenced skills load into EVERY conversation. Every token counts. + +**Target word counts:** +- getting-started workflows: <150 words each +- Frequently-loaded skills: <200 words total +- Other skills: <500 words (still be concise) + +**Techniques:** + +**Move details to tool help:** +```bash +# ❌ BAD: Document all flags in SKILL.md +search-conversations supports --text, --both, --after DATE, --before DATE, --limit N + +# ✅ GOOD: Reference --help +search-conversations supports multiple modes and filters. Run --help for details. +``` + +**Use cross-references:** +```markdown +# ❌ BAD: Repeat workflow details +When searching, dispatch subagent with template... +[20 lines of repeated instructions] + +# ✅ GOOD: Reference other skill +Always use subagents (50-100x context savings). REQUIRED: Use [other-skill-name] for workflow. +``` + +**Compress examples:** +```markdown +# ❌ BAD: Verbose example (42 words) +your human partner: "How did we handle authentication errors in React Router before?" +You: I'll search past conversations for React Router authentication patterns. +[Dispatch subagent with search query: "React Router authentication error handling 401"] + +# ✅ GOOD: Minimal example (20 words) +Partner: "How did we handle auth errors in React Router?" +You: Searching... +[Dispatch subagent → synthesis] +``` + +**Eliminate redundancy:** +- Don't repeat what's in cross-referenced skills +- Don't explain what's obvious from command +- Don't include multiple examples of same pattern + +**Verification:** +```bash +wc -w skills/path/SKILL.md +# getting-started workflows: aim for <150 each +# Other frequently-loaded: aim for <200 total +``` + +**Name by what you DO or core insight:** +- ✅ `condition-based-waiting` > `async-test-helpers` +- ✅ `using-skills` not `skill-usage` +- ✅ `flatten-with-flags` > `data-structure-refactoring` +- ✅ `root-cause-tracing` > `debugging-techniques` + +**Gerunds (-ing) work well for processes:** +- `creating-skills`, `testing-skills`, `debugging-with-logs` +- Active, describes the action you're taking + +### 4. Cross-Referencing Other Skills + +**When writing documentation that references other skills:** + +Use skill name only, with explicit requirement markers: +- ✅ Good: `**REQUIRED SUB-SKILL:** Use superpowers:test-driven-development` +- ✅ Good: `**REQUIRED BACKGROUND:** You MUST understand superpowers:systematic-debugging` +- ❌ Bad: `See skills/testing/test-driven-development` (unclear if required) +- ❌ Bad: `@skills/testing/test-driven-development/SKILL.md` (force-loads, burns context) + +**Why no @ links:** `@` syntax force-loads files immediately, consuming 200k+ context before you need them. + +## Flowchart Usage + +```dot +digraph when_flowchart { + "Need to show information?" [shape=diamond]; + "Decision where I might go wrong?" [shape=diamond]; + "Use markdown" [shape=box]; + "Small inline flowchart" [shape=box]; + + "Need to show information?" -> "Decision where I might go wrong?" [label="yes"]; + "Decision where I might go wrong?" -> "Small inline flowchart" [label="yes"]; + "Decision where I might go wrong?" -> "Use markdown" [label="no"]; +} +``` + +**Use flowcharts ONLY for:** +- Non-obvious decision points +- Process loops where you might stop too early +- "When to use A vs B" decisions + +**Never use flowcharts for:** +- Reference material → Tables, lists +- Code examples → Markdown blocks +- Linear instructions → Numbered lists +- Labels without semantic meaning (step1, helper2) + +See @graphviz-conventions.dot for graphviz style rules. + +**Visualizing for your human partner:** Use `render-graphs.js` in this directory to render a skill's flowcharts to SVG: +```bash +./render-graphs.js ../some-skill # Each diagram separately +./render-graphs.js ../some-skill --combine # All diagrams in one SVG +``` + +## Code Examples + +**One excellent example beats many mediocre ones** + +Choose most relevant language: +- Testing techniques → TypeScript/JavaScript +- System debugging → Shell/Python +- Data processing → Python + +**Good example:** +- Complete and runnable +- Well-commented explaining WHY +- From real scenario +- Shows pattern clearly +- Ready to adapt (not generic template) + +**Don't:** +- Implement in 5+ languages +- Create fill-in-the-blank templates +- Write contrived examples + +You're good at porting - one great example is enough. + +## File Organization + +### Self-Contained Skill +``` +defense-in-depth/ + SKILL.md # Everything inline +``` +When: All content fits, no heavy reference needed + +### Skill with Reusable Tool +``` +condition-based-waiting/ + SKILL.md # Overview + patterns + example.ts # Working helpers to adapt +``` +When: Tool is reusable code, not just narrative + +### Skill with Heavy Reference +``` +pptx/ + SKILL.md # Overview + workflows + pptxgenjs.md # 600 lines API reference + ooxml.md # 500 lines XML structure + scripts/ # Executable tools +``` +When: Reference material too large for inline + +## The Iron Law (Same as TDD) + +``` +NO SKILL WITHOUT A FAILING TEST FIRST +``` + +This applies to NEW skills AND EDITS to existing skills. + +Write skill before testing? Delete it. Start over. +Edit skill without testing? Same violation. + +**No exceptions:** +- Not for "simple additions" +- Not for "just adding a section" +- Not for "documentation updates" +- Don't keep untested changes as "reference" +- Don't "adapt" while running tests +- Delete means delete + +**REQUIRED BACKGROUND:** The superpowers:test-driven-development skill explains why this matters. Same principles apply to documentation. + +## Testing All Skill Types + +Different skill types need different test approaches: + +### Discipline-Enforcing Skills (rules/requirements) + +**Examples:** TDD, verification-before-completion, designing-before-coding + +**Test with:** +- Academic questions: Do they understand the rules? +- Pressure scenarios: Do they comply under stress? +- Multiple pressures combined: time + sunk cost + exhaustion +- Identify rationalizations and add explicit counters + +**Success criteria:** Agent follows rule under maximum pressure + +### Technique Skills (how-to guides) + +**Examples:** condition-based-waiting, root-cause-tracing, defensive-programming + +**Test with:** +- Application scenarios: Can they apply the technique correctly? +- Variation scenarios: Do they handle edge cases? +- Missing information tests: Do instructions have gaps? + +**Success criteria:** Agent successfully applies technique to new scenario + +### Pattern Skills (mental models) + +**Examples:** reducing-complexity, information-hiding concepts + +**Test with:** +- Recognition scenarios: Do they recognize when pattern applies? +- Application scenarios: Can they use the mental model? +- Counter-examples: Do they know when NOT to apply? + +**Success criteria:** Agent correctly identifies when/how to apply pattern + +### Reference Skills (documentation/APIs) + +**Examples:** API documentation, command references, library guides + +**Test with:** +- Retrieval scenarios: Can they find the right information? +- Application scenarios: Can they use what they found correctly? +- Gap testing: Are common use cases covered? + +**Success criteria:** Agent finds and correctly applies reference information + +## Common Rationalizations for Skipping Testing + +| Excuse | Reality | +|--------|---------| +| "Skill is obviously clear" | Clear to you ≠ clear to other agents. Test it. | +| "It's just a reference" | References can have gaps, unclear sections. Test retrieval. | +| "Testing is overkill" | Untested skills have issues. Always. 15 min testing saves hours. | +| "I'll test if problems emerge" | Problems = agents can't use skill. Test BEFORE deploying. | +| "Too tedious to test" | Testing is less tedious than debugging bad skill in production. | +| "I'm confident it's good" | Overconfidence guarantees issues. Test anyway. | +| "Academic review is enough" | Reading ≠ using. Test application scenarios. | +| "No time to test" | Deploying untested skill wastes more time fixing it later. | + +**All of these mean: Test before deploying. No exceptions.** + +## Bulletproofing Skills Against Rationalization + +Skills that enforce discipline (like TDD) need to resist rationalization. Agents are smart and will find loopholes when under pressure. + +**Psychology note:** Understanding WHY persuasion techniques work helps you apply them systematically. See persuasion-principles.md for research foundation (Cialdini, 2021; Meincke et al., 2025) on authority, commitment, scarcity, social proof, and unity principles. + +### Close Every Loophole Explicitly + +Don't just state the rule - forbid specific workarounds: + +<Bad> +```markdown +Write code before test? Delete it. +``` +</Bad> + +<Good> +```markdown +Write code before test? Delete it. Start over. + +**No exceptions:** +- Don't keep it as "reference" +- Don't "adapt" it while writing tests +- Don't look at it +- Delete means delete +``` +</Good> + +### Address "Spirit vs Letter" Arguments + +Add foundational principle early: + +```markdown +**Violating the letter of the rules is violating the spirit of the rules.** +``` + +This cuts off entire class of "I'm following the spirit" rationalizations. + +### Build Rationalization Table + +Capture rationalizations from baseline testing (see Testing section below). Every excuse agents make goes in the table: + +```markdown +| Excuse | Reality | +|--------|---------| +| "Too simple to test" | Simple code breaks. Test takes 30 seconds. | +| "I'll test after" | Tests passing immediately prove nothing. | +| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" | +``` + +### Create Red Flags List + +Make it easy for agents to self-check when rationalizing: + +```markdown +## Red Flags - STOP and Start Over + +- Code before test +- "I already manually tested it" +- "Tests after achieve the same purpose" +- "It's about spirit not ritual" +- "This is different because..." + +**All of these mean: Delete code. Start over with TDD.** +``` + +### Update CSO for Violation Symptoms + +Add to description: symptoms of when you're ABOUT to violate the rule: + +```yaml +description: use when implementing any feature or bugfix, before writing implementation code +``` + +## RED-GREEN-REFACTOR for Skills + +Follow the TDD cycle: + +### RED: Write Failing Test (Baseline) + +Run pressure scenario with subagent WITHOUT the skill. Document exact behavior: +- What choices did they make? +- What rationalizations did they use (verbatim)? +- Which pressures triggered violations? + +This is "watch the test fail" - you must see what agents naturally do before writing the skill. + +### GREEN: Write Minimal Skill + +Write skill that addresses those specific rationalizations. Don't add extra content for hypothetical cases. + +Run same scenarios WITH skill. Agent should now comply. + +### REFACTOR: Close Loopholes + +Agent found new rationalization? Add explicit counter. Re-test until bulletproof. + +**Testing methodology:** See @testing-skills-with-subagents.md for the complete testing methodology: +- How to write pressure scenarios +- Pressure types (time, sunk cost, authority, exhaustion) +- Plugging holes systematically +- Meta-testing techniques + +## Anti-Patterns + +### ❌ Narrative Example +"In session 2025-10-03, we found empty projectDir caused..." +**Why bad:** Too specific, not reusable + +### ❌ Multi-Language Dilution +example-js.js, example-py.py, example-go.go +**Why bad:** Mediocre quality, maintenance burden + +### ❌ Code in Flowcharts +```dot +step1 [label="import fs"]; +step2 [label="read file"]; +``` +**Why bad:** Can't copy-paste, hard to read + +### ❌ Generic Labels +helper1, helper2, step3, pattern4 +**Why bad:** Labels should have semantic meaning + +## STOP: Before Moving to Next Skill + +**After writing ANY skill, you MUST STOP and complete the deployment process.** + +**Do NOT:** +- Create multiple skills in batch without testing each +- Move to next skill before current one is verified +- Skip testing because "batching is more efficient" + +**The deployment checklist below is MANDATORY for EACH skill.** + +Deploying untested skills = deploying untested code. It's a violation of quality standards. + +## Skill Creation Checklist (TDD Adapted) + +**IMPORTANT: Use TodoWrite to create todos for EACH checklist item below.** + +**RED Phase - Write Failing Test:** +- [ ] Create pressure scenarios (3+ combined pressures for discipline skills) +- [ ] Run scenarios WITHOUT skill - document baseline behavior verbatim +- [ ] Identify patterns in rationalizations/failures + +**GREEN Phase - Write Minimal Skill:** +- [ ] Name uses only letters, numbers, hyphens (no parentheses/special chars) +- [ ] YAML frontmatter with only name and description (max 1024 chars) +- [ ] Description starts with "Use when..." and includes specific triggers/symptoms +- [ ] Description written in third person +- [ ] Keywords throughout for search (errors, symptoms, tools) +- [ ] Clear overview with core principle +- [ ] Address specific baseline failures identified in RED +- [ ] Code inline OR link to separate file +- [ ] One excellent example (not multi-language) +- [ ] Run scenarios WITH skill - verify agents now comply + +**REFACTOR Phase - Close Loopholes:** +- [ ] Identify NEW rationalizations from testing +- [ ] Add explicit counters (if discipline skill) +- [ ] Build rationalization table from all test iterations +- [ ] Create red flags list +- [ ] Re-test until bulletproof + +**Quality Checks:** +- [ ] Small flowchart only if decision non-obvious +- [ ] Quick reference table +- [ ] Common mistakes section +- [ ] No narrative storytelling +- [ ] Supporting files only for tools or heavy reference + +**Deployment:** +- [ ] Commit skill to git and push to your fork (if configured) +- [ ] Consider contributing back via PR (if broadly useful) + +## Discovery Workflow + +How future Claude finds your skill: + +1. **Encounters problem** ("tests are flaky") +3. **Finds SKILL** (description matches) +4. **Scans overview** (is this relevant?) +5. **Reads patterns** (quick reference table) +6. **Loads example** (only when implementing) + +**Optimize for this flow** - put searchable terms early and often. + +## The Bottom Line + +**Creating skills IS TDD for process documentation.** + +Same Iron Law: No skill without failing test first. +Same cycle: RED (baseline) → GREEN (write skill) → REFACTOR (close loopholes). +Same benefits: Better quality, fewer surprises, bulletproof results. + +If you follow TDD for code, follow it for skills. It's the same discipline applied to documentation. diff --git a/account/admin/skills/superpowers-writing-skills/anthropic-best-practices.md b/account/admin/skills/superpowers-writing-skills/anthropic-best-practices.md new file mode 100644 index 0000000..a5a7d07 --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/anthropic-best-practices.md @@ -0,0 +1,1150 @@ +# Skill authoring best practices + +> Learn how to write effective Skills that Claude can discover and use successfully. + +Good Skills are concise, well-structured, and tested with real usage. This guide provides practical authoring decisions to help you write Skills that Claude can discover and use effectively. + +For conceptual background on how Skills work, see the [Skills overview](/en/docs/agents-and-tools/agent-skills/overview). + +## Core principles + +### Concise is key + +The [context window](https://platform.claude.com/docs/en/build-with-claude/context-windows) is a public good. Your Skill shares the context window with everything else Claude needs to know, including: + +* The system prompt +* Conversation history +* Other Skills' metadata +* Your actual request + +Not every token in your Skill has an immediate cost. At startup, only the metadata (name and description) from all Skills is pre-loaded. Claude reads SKILL.md only when the Skill becomes relevant, and reads additional files only as needed. However, being concise in SKILL.md still matters: once Claude loads it, every token competes with conversation history and other context. + +**Default assumption**: Claude is already very smart + +Only add context Claude doesn't already have. Challenge each piece of information: + +* "Does Claude really need this explanation?" +* "Can I assume Claude knows this?" +* "Does this paragraph justify its token cost?" + +**Good example: Concise** (approximately 50 tokens): + +````markdown theme={null} +## Extract PDF text + +Use pdfplumber for text extraction: + +```python +import pdfplumber + +with pdfplumber.open("file.pdf") as pdf: + text = pdf.pages[0].extract_text() +``` +```` + +**Bad example: Too verbose** (approximately 150 tokens): + +```markdown theme={null} +## Extract PDF text + +PDF (Portable Document Format) files are a common file format that contains +text, images, and other content. To extract text from a PDF, you'll need to +use a library. There are many libraries available for PDF processing, but we +recommend pdfplumber because it's easy to use and handles most cases well. +First, you'll need to install it using pip. Then you can use the code below... +``` + +The concise version assumes Claude knows what PDFs are and how libraries work. + +### Set appropriate degrees of freedom + +Match the level of specificity to the task's fragility and variability. + +**High freedom** (text-based instructions): + +Use when: + +* Multiple approaches are valid +* Decisions depend on context +* Heuristics guide the approach + +Example: + +```markdown theme={null} +## Code review process + +1. Analyze the code structure and organization +2. Check for potential bugs or edge cases +3. Suggest improvements for readability and maintainability +4. Verify adherence to project conventions +``` + +**Medium freedom** (pseudocode or scripts with parameters): + +Use when: + +* A preferred pattern exists +* Some variation is acceptable +* Configuration affects behavior + +Example: + +````markdown theme={null} +## Generate report + +Use this template and customize as needed: + +```python +def generate_report(data, format="markdown", include_charts=True): + # Process data + # Generate output in specified format + # Optionally include visualizations +``` +```` + +**Low freedom** (specific scripts, few or no parameters): + +Use when: + +* Operations are fragile and error-prone +* Consistency is critical +* A specific sequence must be followed + +Example: + +````markdown theme={null} +## Database migration + +Run exactly this script: + +```bash +python scripts/migrate.py --verify --backup +``` + +Do not modify the command or add additional flags. +```` + +**Analogy**: Think of Claude as a robot exploring a path: + +* **Narrow bridge with cliffs on both sides**: There's only one safe way forward. Provide specific guardrails and exact instructions (low freedom). Example: database migrations that must run in exact sequence. +* **Open field with no hazards**: Many paths lead to success. Give general direction and trust Claude to find the best route (high freedom). Example: code reviews where context determines the best approach. + +### Test with all models you plan to use + +Skills act as additions to models, so effectiveness depends on the underlying model. Test your Skill with all the models you plan to use it with. + +**Testing considerations by model**: + +* **Claude Haiku** (fast, economical): Does the Skill provide enough guidance? +* **Claude Sonnet** (balanced): Is the Skill clear and efficient? +* **Claude Opus** (powerful reasoning): Does the Skill avoid over-explaining? + +What works perfectly for Opus might need more detail for Haiku. If you plan to use your Skill across multiple models, aim for instructions that work well with all of them. + +## Skill structure + +<Note> + **YAML Frontmatter**: The SKILL.md frontmatter supports two fields: + + * `name` - Human-readable name of the Skill (64 characters maximum) + * `description` - One-line description of what the Skill does and when to use it (1024 characters maximum) + + For complete Skill structure details, see the [Skills overview](/en/docs/agents-and-tools/agent-skills/overview#skill-structure). +</Note> + +### Naming conventions + +Use consistent naming patterns to make Skills easier to reference and discuss. We recommend using **gerund form** (verb + -ing) for Skill names, as this clearly describes the activity or capability the Skill provides. + +**Good naming examples (gerund form)**: + +* "Processing PDFs" +* "Analyzing spreadsheets" +* "Managing databases" +* "Testing code" +* "Writing documentation" + +**Acceptable alternatives**: + +* Noun phrases: "PDF Processing", "Spreadsheet Analysis" +* Action-oriented: "Process PDFs", "Analyze Spreadsheets" + +**Avoid**: + +* Vague names: "Helper", "Utils", "Tools" +* Overly generic: "Documents", "Data", "Files" +* Inconsistent patterns within your skill collection + +Consistent naming makes it easier to: + +* Reference Skills in documentation and conversations +* Understand what a Skill does at a glance +* Organize and search through multiple Skills +* Maintain a professional, cohesive skill library + +### Writing effective descriptions + +The `description` field enables Skill discovery and should include both what the Skill does and when to use it. + +<Warning> + **Always write in third person**. The description is injected into the system prompt, and inconsistent point-of-view can cause discovery problems. + + * **Good:** "Processes Excel files and generates reports" + * **Avoid:** "I can help you process Excel files" + * **Avoid:** "You can use this to process Excel files" +</Warning> + +**Be specific and include key terms**. Include both what the Skill does and specific triggers/contexts for when to use it. + +Each Skill has exactly one description field. The description is critical for skill selection: Claude uses it to choose the right Skill from potentially 100+ available Skills. Your description must provide enough detail for Claude to know when to select this Skill, while the rest of SKILL.md provides the implementation details. + +Effective examples: + +**PDF Processing skill:** + +```yaml theme={null} +description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. +``` + +**Excel Analysis skill:** + +```yaml theme={null} +description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files. +``` + +**Git Commit Helper skill:** + +```yaml theme={null} +description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes. +``` + +Avoid vague descriptions like these: + +```yaml theme={null} +description: Helps with documents +``` + +```yaml theme={null} +description: Processes data +``` + +```yaml theme={null} +description: Does stuff with files +``` + +### Progressive disclosure patterns + +SKILL.md serves as an overview that points Claude to detailed materials as needed, like a table of contents in an onboarding guide. For an explanation of how progressive disclosure works, see [How Skills work](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work) in the overview. + +**Practical guidance:** + +* Keep SKILL.md body under 500 lines for optimal performance +* Split content into separate files when approaching this limit +* Use the patterns below to organize instructions, code, and resources effectively + +#### Visual overview: From simple to complex + +A basic Skill starts with just a SKILL.md file containing metadata and instructions: + +<img src="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=87782ff239b297d9a9e8e1b72ed72db9" alt="Simple SKILL.md file showing YAML frontmatter and markdown body" data-og-width="2048" width="2048" data-og-height="1153" height="1153" data-path="images/agent-skills-simple-file.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=280&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=c61cc33b6f5855809907f7fda94cd80e 280w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=560&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=90d2c0c1c76b36e8d485f49e0810dbfd 560w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=840&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=ad17d231ac7b0bea7e5b4d58fb4aeabb 840w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=1100&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=f5d0a7a3c668435bb0aee9a3a8f8c329 1100w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=1650&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=0e927c1af9de5799cfe557d12249f6e6 1650w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-simple-file.png?w=2500&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=46bbb1a51dd4c8202a470ac8c80a893d 2500w" /> + +As your Skill grows, you can bundle additional content that Claude loads only when needed: + +<img src="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=a5e0aa41e3d53985a7e3e43668a33ea3" alt="Bundling additional reference files like reference.md and forms.md." data-og-width="2048" width="2048" data-og-height="1327" height="1327" data-path="images/agent-skills-bundling-content.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=280&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=f8a0e73783e99b4a643d79eac86b70a2 280w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=560&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=dc510a2a9d3f14359416b706f067904a 560w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=840&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=82cd6286c966303f7dd914c28170e385 840w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=1100&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=56f3be36c77e4fe4b523df209a6824c6 1100w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=1650&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=d22b5161b2075656417d56f41a74f3dd 1650w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-bundling-content.png?w=2500&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=3dd4bdd6850ffcc96c6c45fcb0acd6eb 2500w" /> + +The complete Skill directory structure might look like this: + +``` +pdf/ +├── SKILL.md # Main instructions (loaded when triggered) +├── FORMS.md # Form-filling guide (loaded as needed) +├── reference.md # API reference (loaded as needed) +├── examples.md # Usage examples (loaded as needed) +└── scripts/ + ├── analyze_form.py # Utility script (executed, not loaded) + ├── fill_form.py # Form filling script + └── validate.py # Validation script +``` + +#### Pattern 1: High-level guide with references + +````markdown theme={null} +--- +name: PDF Processing +description: Extracts text and tables from PDF files, fills forms, and merges documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. +--- + +# PDF Processing + +## Quick start + +Extract text with pdfplumber: +```python +import pdfplumber +with pdfplumber.open("file.pdf") as pdf: + text = pdf.pages[0].extract_text() +``` + +## Advanced features + +**Form filling**: See [FORMS.md](FORMS.md) for complete guide +**API reference**: See [REFERENCE.md](REFERENCE.md) for all methods +**Examples**: See [EXAMPLES.md](EXAMPLES.md) for common patterns +```` + +Claude loads FORMS.md, REFERENCE.md, or EXAMPLES.md only when needed. + +#### Pattern 2: Domain-specific organization + +For Skills with multiple domains, organize content by domain to avoid loading irrelevant context. When a user asks about sales metrics, Claude only needs to read sales-related schemas, not finance or marketing data. This keeps token usage low and context focused. + +``` +bigquery-skill/ +├── SKILL.md (overview and navigation) +└── reference/ + ├── finance.md (revenue, billing metrics) + ├── sales.md (opportunities, pipeline) + ├── product.md (API usage, features) + └── marketing.md (campaigns, attribution) +``` + +````markdown SKILL.md theme={null} +# BigQuery Data Analysis + +## Available datasets + +**Finance**: Revenue, ARR, billing → See [reference/finance.md](reference/finance.md) +**Sales**: Opportunities, pipeline, accounts → See [reference/sales.md](reference/sales.md) +**Product**: API usage, features, adoption → See [reference/product.md](reference/product.md) +**Marketing**: Campaigns, attribution, email → See [reference/marketing.md](reference/marketing.md) + +## Quick search + +Find specific metrics using grep: + +```bash +grep -i "revenue" reference/finance.md +grep -i "pipeline" reference/sales.md +grep -i "api usage" reference/product.md +``` +```` + +#### Pattern 3: Conditional details + +Show basic content, link to advanced content: + +```markdown theme={null} +# DOCX Processing + +## Creating documents + +Use docx-js for new documents. See [DOCX-JS.md](DOCX-JS.md). + +## Editing documents + +For simple edits, modify the XML directly. + +**For tracked changes**: See [REDLINING.md](REDLINING.md) +**For OOXML details**: See [OOXML.md](OOXML.md) +``` + +Claude reads REDLINING.md or OOXML.md only when the user needs those features. + +### Avoid deeply nested references + +Claude may partially read files when they're referenced from other referenced files. When encountering nested references, Claude might use commands like `head -100` to preview content rather than reading entire files, resulting in incomplete information. + +**Keep references one level deep from SKILL.md**. All reference files should link directly from SKILL.md to ensure Claude reads complete files when needed. + +**Bad example: Too deep**: + +```markdown theme={null} +# SKILL.md +See [advanced.md](advanced.md)... + +# advanced.md +See [details.md](details.md)... + +# details.md +Here's the actual information... +``` + +**Good example: One level deep**: + +```markdown theme={null} +# SKILL.md + +**Basic usage**: [instructions in SKILL.md] +**Advanced features**: See [advanced.md](advanced.md) +**API reference**: See [reference.md](reference.md) +**Examples**: See [examples.md](examples.md) +``` + +### Structure longer reference files with table of contents + +For reference files longer than 100 lines, include a table of contents at the top. This ensures Claude can see the full scope of available information even when previewing with partial reads. + +**Example**: + +```markdown theme={null} +# API Reference + +## Contents +- Authentication and setup +- Core methods (create, read, update, delete) +- Advanced features (batch operations, webhooks) +- Error handling patterns +- Code examples + +## Authentication and setup +... + +## Core methods +... +``` + +Claude can then read the complete file or jump to specific sections as needed. + +For details on how this filesystem-based architecture enables progressive disclosure, see the [Runtime environment](#runtime-environment) section in the Advanced section below. + +## Workflows and feedback loops + +### Use workflows for complex tasks + +Break complex operations into clear, sequential steps. For particularly complex workflows, provide a checklist that Claude can copy into its response and check off as it progresses. + +**Example 1: Research synthesis workflow** (for Skills without code): + +````markdown theme={null} +## Research synthesis workflow + +Copy this checklist and track your progress: + +``` +Research Progress: +- [ ] Step 1: Read all source documents +- [ ] Step 2: Identify key themes +- [ ] Step 3: Cross-reference claims +- [ ] Step 4: Create structured summary +- [ ] Step 5: Verify citations +``` + +**Step 1: Read all source documents** + +Review each document in the `sources/` directory. Note the main arguments and supporting evidence. + +**Step 2: Identify key themes** + +Look for patterns across sources. What themes appear repeatedly? Where do sources agree or disagree? + +**Step 3: Cross-reference claims** + +For each major claim, verify it appears in the source material. Note which source supports each point. + +**Step 4: Create structured summary** + +Organize findings by theme. Include: +- Main claim +- Supporting evidence from sources +- Conflicting viewpoints (if any) + +**Step 5: Verify citations** + +Check that every claim references the correct source document. If citations are incomplete, return to Step 3. +```` + +This example shows how workflows apply to analysis tasks that don't require code. The checklist pattern works for any complex, multi-step process. + +**Example 2: PDF form filling workflow** (for Skills with code): + +````markdown theme={null} +## PDF form filling workflow + +Copy this checklist and check off items as you complete them: + +``` +Task Progress: +- [ ] Step 1: Analyze the form (run analyze_form.py) +- [ ] Step 2: Create field mapping (edit fields.json) +- [ ] Step 3: Validate mapping (run validate_fields.py) +- [ ] Step 4: Fill the form (run fill_form.py) +- [ ] Step 5: Verify output (run verify_output.py) +``` + +**Step 1: Analyze the form** + +Run: `python scripts/analyze_form.py input.pdf` + +This extracts form fields and their locations, saving to `fields.json`. + +**Step 2: Create field mapping** + +Edit `fields.json` to add values for each field. + +**Step 3: Validate mapping** + +Run: `python scripts/validate_fields.py fields.json` + +Fix any validation errors before continuing. + +**Step 4: Fill the form** + +Run: `python scripts/fill_form.py input.pdf fields.json output.pdf` + +**Step 5: Verify output** + +Run: `python scripts/verify_output.py output.pdf` + +If verification fails, return to Step 2. +```` + +Clear steps prevent Claude from skipping critical validation. The checklist helps both Claude and you track progress through multi-step workflows. + +### Implement feedback loops + +**Common pattern**: Run validator → fix errors → repeat + +This pattern greatly improves output quality. + +**Example 1: Style guide compliance** (for Skills without code): + +```markdown theme={null} +## Content review process + +1. Draft your content following the guidelines in STYLE_GUIDE.md +2. Review against the checklist: + - Check terminology consistency + - Verify examples follow the standard format + - Confirm all required sections are present +3. If issues found: + - Note each issue with specific section reference + - Revise the content + - Review the checklist again +4. Only proceed when all requirements are met +5. Finalize and save the document +``` + +This shows the validation loop pattern using reference documents instead of scripts. The "validator" is STYLE\_GUIDE.md, and Claude performs the check by reading and comparing. + +**Example 2: Document editing process** (for Skills with code): + +```markdown theme={null} +## Document editing process + +1. Make your edits to `word/document.xml` +2. **Validate immediately**: `python ooxml/scripts/validate.py unpacked_dir/` +3. If validation fails: + - Review the error message carefully + - Fix the issues in the XML + - Run validation again +4. **Only proceed when validation passes** +5. Rebuild: `python ooxml/scripts/pack.py unpacked_dir/ output.docx` +6. Test the output document +``` + +The validation loop catches errors early. + +## Content guidelines + +### Avoid time-sensitive information + +Don't include information that will become outdated: + +**Bad example: Time-sensitive** (will become wrong): + +```markdown theme={null} +If you're doing this before August 2025, use the old API. +After August 2025, use the new API. +``` + +**Good example** (use "old patterns" section): + +```markdown theme={null} +## Current method + +Use the v2 API endpoint: `api.example.com/v2/messages` + +## Old patterns + +<details> +<summary>Legacy v1 API (deprecated 2025-08)</summary> + +The v1 API used: `api.example.com/v1/messages` + +This endpoint is no longer supported. +</details> +``` + +The old patterns section provides historical context without cluttering the main content. + +### Use consistent terminology + +Choose one term and use it throughout the Skill: + +**Good - Consistent**: + +* Always "API endpoint" +* Always "field" +* Always "extract" + +**Bad - Inconsistent**: + +* Mix "API endpoint", "URL", "API route", "path" +* Mix "field", "box", "element", "control" +* Mix "extract", "pull", "get", "retrieve" + +Consistency helps Claude understand and follow instructions. + +## Common patterns + +### Template pattern + +Provide templates for output format. Match the level of strictness to your needs. + +**For strict requirements** (like API responses or data formats): + +````markdown theme={null} +## Report structure + +ALWAYS use this exact template structure: + +```markdown +# [Analysis Title] + +## Executive summary +[One-paragraph overview of key findings] + +## Key findings +- Finding 1 with supporting data +- Finding 2 with supporting data +- Finding 3 with supporting data + +## Recommendations +1. Specific actionable recommendation +2. Specific actionable recommendation +``` +```` + +**For flexible guidance** (when adaptation is useful): + +````markdown theme={null} +## Report structure + +Here is a sensible default format, but use your best judgment based on the analysis: + +```markdown +# [Analysis Title] + +## Executive summary +[Overview] + +## Key findings +[Adapt sections based on what you discover] + +## Recommendations +[Tailor to the specific context] +``` + +Adjust sections as needed for the specific analysis type. +```` + +### Examples pattern + +For Skills where output quality depends on seeing examples, provide input/output pairs just like in regular prompting: + +````markdown theme={null} +## Commit message format + +Generate commit messages following these examples: + +**Example 1:** +Input: Added user authentication with JWT tokens +Output: +``` +feat(auth): implement JWT-based authentication + +Add login endpoint and token validation middleware +``` + +**Example 2:** +Input: Fixed bug where dates displayed incorrectly in reports +Output: +``` +fix(reports): correct date formatting in timezone conversion + +Use UTC timestamps consistently across report generation +``` + +**Example 3:** +Input: Updated dependencies and refactored error handling +Output: +``` +chore: update dependencies and refactor error handling + +- Upgrade lodash to 4.17.21 +- Standardize error response format across endpoints +``` + +Follow this style: type(scope): brief description, then detailed explanation. +```` + +Examples help Claude understand the desired style and level of detail more clearly than descriptions alone. + +### Conditional workflow pattern + +Guide Claude through decision points: + +```markdown theme={null} +## Document modification workflow + +1. Determine the modification type: + + **Creating new content?** → Follow "Creation workflow" below + **Editing existing content?** → Follow "Editing workflow" below + +2. Creation workflow: + - Use docx-js library + - Build document from scratch + - Export to .docx format + +3. Editing workflow: + - Unpack existing document + - Modify XML directly + - Validate after each change + - Repack when complete +``` + +<Tip> + If workflows become large or complicated with many steps, consider pushing them into separate files and tell Claude to read the appropriate file based on the task at hand. +</Tip> + +## Evaluation and iteration + +### Build evaluations first + +**Create evaluations BEFORE writing extensive documentation.** This ensures your Skill solves real problems rather than documenting imagined ones. + +**Evaluation-driven development:** + +1. **Identify gaps**: Run Claude on representative tasks without a Skill. Document specific failures or missing context +2. **Create evaluations**: Build three scenarios that test these gaps +3. **Establish baseline**: Measure Claude's performance without the Skill +4. **Write minimal instructions**: Create just enough content to address the gaps and pass evaluations +5. **Iterate**: Execute evaluations, compare against baseline, and refine + +This approach ensures you're solving actual problems rather than anticipating requirements that may never materialize. + +**Evaluation structure**: + +```json theme={null} +{ + "skills": ["pdf-processing"], + "query": "Extract all text from this PDF file and save it to output.txt", + "files": ["test-files/document.pdf"], + "expected_behavior": [ + "Successfully reads the PDF file using an appropriate PDF processing library or command-line tool", + "Extracts text content from all pages in the document without missing any pages", + "Saves the extracted text to a file named output.txt in a clear, readable format" + ] +} +``` + +<Note> + This example demonstrates a data-driven evaluation with a simple testing rubric. We do not currently provide a built-in way to run these evaluations. Users can create their own evaluation system. Evaluations are your source of truth for measuring Skill effectiveness. +</Note> + +### Develop Skills iteratively with Claude + +The most effective Skill development process involves Claude itself. Work with one instance of Claude ("Claude A") to create a Skill that will be used by other instances ("Claude B"). Claude A helps you design and refine instructions, while Claude B tests them in real tasks. This works because Claude models understand both how to write effective agent instructions and what information agents need. + +**Creating a new Skill:** + +1. **Complete a task without a Skill**: Work through a problem with Claude A using normal prompting. As you work, you'll naturally provide context, explain preferences, and share procedural knowledge. Notice what information you repeatedly provide. + +2. **Identify the reusable pattern**: After completing the task, identify what context you provided that would be useful for similar future tasks. + + **Example**: If you worked through a BigQuery analysis, you might have provided table names, field definitions, filtering rules (like "always exclude test accounts"), and common query patterns. + +3. **Ask Claude A to create a Skill**: "Create a Skill that captures this BigQuery analysis pattern we just used. Include the table schemas, naming conventions, and the rule about filtering test accounts." + + <Tip> + Claude models understand the Skill format and structure natively. You don't need special system prompts or a "writing skills" skill to get Claude to help create Skills. Simply ask Claude to create a Skill and it will generate properly structured SKILL.md content with appropriate frontmatter and body content. + </Tip> + +4. **Review for conciseness**: Check that Claude A hasn't added unnecessary explanations. Ask: "Remove the explanation about what win rate means - Claude already knows that." + +5. **Improve information architecture**: Ask Claude A to organize the content more effectively. For example: "Organize this so the table schema is in a separate reference file. We might add more tables later." + +6. **Test on similar tasks**: Use the Skill with Claude B (a fresh instance with the Skill loaded) on related use cases. Observe whether Claude B finds the right information, applies rules correctly, and handles the task successfully. + +7. **Iterate based on observation**: If Claude B struggles or misses something, return to Claude A with specifics: "When Claude used this Skill, it forgot to filter by date for Q4. Should we add a section about date filtering patterns?" + +**Iterating on existing Skills:** + +The same hierarchical pattern continues when improving Skills. You alternate between: + +* **Working with Claude A** (the expert who helps refine the Skill) +* **Testing with Claude B** (the agent using the Skill to perform real work) +* **Observing Claude B's behavior** and bringing insights back to Claude A + +1. **Use the Skill in real workflows**: Give Claude B (with the Skill loaded) actual tasks, not test scenarios + +2. **Observe Claude B's behavior**: Note where it struggles, succeeds, or makes unexpected choices + + **Example observation**: "When I asked Claude B for a regional sales report, it wrote the query but forgot to filter out test accounts, even though the Skill mentions this rule." + +3. **Return to Claude A for improvements**: Share the current SKILL.md and describe what you observed. Ask: "I noticed Claude B forgot to filter test accounts when I asked for a regional report. The Skill mentions filtering, but maybe it's not prominent enough?" + +4. **Review Claude A's suggestions**: Claude A might suggest reorganizing to make rules more prominent, using stronger language like "MUST filter" instead of "always filter", or restructuring the workflow section. + +5. **Apply and test changes**: Update the Skill with Claude A's refinements, then test again with Claude B on similar requests + +6. **Repeat based on usage**: Continue this observe-refine-test cycle as you encounter new scenarios. Each iteration improves the Skill based on real agent behavior, not assumptions. + +**Gathering team feedback:** + +1. Share Skills with teammates and observe their usage +2. Ask: Does the Skill activate when expected? Are instructions clear? What's missing? +3. Incorporate feedback to address blind spots in your own usage patterns + +**Why this approach works**: Claude A understands agent needs, you provide domain expertise, Claude B reveals gaps through real usage, and iterative refinement improves Skills based on observed behavior rather than assumptions. + +### Observe how Claude navigates Skills + +As you iterate on Skills, pay attention to how Claude actually uses them in practice. Watch for: + +* **Unexpected exploration paths**: Does Claude read files in an order you didn't anticipate? This might indicate your structure isn't as intuitive as you thought +* **Missed connections**: Does Claude fail to follow references to important files? Your links might need to be more explicit or prominent +* **Overreliance on certain sections**: If Claude repeatedly reads the same file, consider whether that content should be in the main SKILL.md instead +* **Ignored content**: If Claude never accesses a bundled file, it might be unnecessary or poorly signaled in the main instructions + +Iterate based on these observations rather than assumptions. The 'name' and 'description' in your Skill's metadata are particularly critical. Claude uses these when deciding whether to trigger the Skill in response to the current task. Make sure they clearly describe what the Skill does and when it should be used. + +## Anti-patterns to avoid + +### Avoid Windows-style paths + +Always use forward slashes in file paths, even on Windows: + +* ✓ **Good**: `scripts/helper.py`, `reference/guide.md` +* ✗ **Avoid**: `scripts\helper.py`, `reference\guide.md` + +Unix-style paths work across all platforms, while Windows-style paths cause errors on Unix systems. + +### Avoid offering too many options + +Don't present multiple approaches unless necessary: + +````markdown theme={null} +**Bad example: Too many choices** (confusing): +"You can use pypdf, or pdfplumber, or PyMuPDF, or pdf2image, or..." + +**Good example: Provide a default** (with escape hatch): +"Use pdfplumber for text extraction: +```python +import pdfplumber +``` + +For scanned PDFs requiring OCR, use pdf2image with pytesseract instead." +```` + +## Advanced: Skills with executable code + +The sections below focus on Skills that include executable scripts. If your Skill uses only markdown instructions, skip to [Checklist for effective Skills](#checklist-for-effective-skills). + +### Solve, don't punt + +When writing scripts for Skills, handle error conditions rather than punting to Claude. + +**Good example: Handle errors explicitly**: + +```python theme={null} +def process_file(path): + """Process a file, creating it if it doesn't exist.""" + try: + with open(path) as f: + return f.read() + except FileNotFoundError: + # Create file with default content instead of failing + print(f"File {path} not found, creating default") + with open(path, 'w') as f: + f.write('') + return '' + except PermissionError: + # Provide alternative instead of failing + print(f"Cannot access {path}, using default") + return '' +``` + +**Bad example: Punt to Claude**: + +```python theme={null} +def process_file(path): + # Just fail and let Claude figure it out + return open(path).read() +``` + +Configuration parameters should also be justified and documented to avoid "voodoo constants" (Ousterhout's law). If you don't know the right value, how will Claude determine it? + +**Good example: Self-documenting**: + +```python theme={null} +# HTTP requests typically complete within 30 seconds +# Longer timeout accounts for slow connections +REQUEST_TIMEOUT = 30 + +# Three retries balances reliability vs speed +# Most intermittent failures resolve by the second retry +MAX_RETRIES = 3 +``` + +**Bad example: Magic numbers**: + +```python theme={null} +TIMEOUT = 47 # Why 47? +RETRIES = 5 # Why 5? +``` + +### Provide utility scripts + +Even if Claude could write a script, pre-made scripts offer advantages: + +**Benefits of utility scripts**: + +* More reliable than generated code +* Save tokens (no need to include code in context) +* Save time (no code generation required) +* Ensure consistency across uses + +<img src="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=4bbc45f2c2e0bee9f2f0d5da669bad00" alt="Bundling executable scripts alongside instruction files" data-og-width="2048" width="2048" data-og-height="1154" height="1154" data-path="images/agent-skills-executable-scripts.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=280&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=9a04e6535a8467bfeea492e517de389f 280w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=560&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=e49333ad90141af17c0d7651cca7216b 560w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=840&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=954265a5df52223d6572b6214168c428 840w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=1100&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=2ff7a2d8f2a83ee8af132b29f10150fd 1100w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=1650&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=48ab96245e04077f4d15e9170e081cfb 1650w, https://mintcdn.com/anthropic-claude-docs/4Bny2bjzuGBK7o00/images/agent-skills-executable-scripts.png?w=2500&fit=max&auto=format&n=4Bny2bjzuGBK7o00&q=85&s=0301a6c8b3ee879497cc5b5483177c90 2500w" /> + +The diagram above shows how executable scripts work alongside instruction files. The instruction file (forms.md) references the script, and Claude can execute it without loading its contents into context. + +**Important distinction**: Make clear in your instructions whether Claude should: + +* **Execute the script** (most common): "Run `analyze_form.py` to extract fields" +* **Read it as reference** (for complex logic): "See `analyze_form.py` for the field extraction algorithm" + +For most utility scripts, execution is preferred because it's more reliable and efficient. See the [Runtime environment](#runtime-environment) section below for details on how script execution works. + +**Example**: + +````markdown theme={null} +## Utility scripts + +**analyze_form.py**: Extract all form fields from PDF + +```bash +python scripts/analyze_form.py input.pdf > fields.json +``` + +Output format: +```json +{ + "field_name": {"type": "text", "x": 100, "y": 200}, + "signature": {"type": "sig", "x": 150, "y": 500} +} +``` + +**validate_boxes.py**: Check for overlapping bounding boxes + +```bash +python scripts/validate_boxes.py fields.json +# Returns: "OK" or lists conflicts +``` + +**fill_form.py**: Apply field values to PDF + +```bash +python scripts/fill_form.py input.pdf fields.json output.pdf +``` +```` + +### Use visual analysis + +When inputs can be rendered as images, have Claude analyze them: + +````markdown theme={null} +## Form layout analysis + +1. Convert PDF to images: + ```bash + python scripts/pdf_to_images.py form.pdf + ``` + +2. Analyze each page image to identify form fields +3. Claude can see field locations and types visually +```` + +<Note> + In this example, you'd need to write the `pdf_to_images.py` script. +</Note> + +Claude's vision capabilities help understand layouts and structures. + +### Create verifiable intermediate outputs + +When Claude performs complex, open-ended tasks, it can make mistakes. The "plan-validate-execute" pattern catches errors early by having Claude first create a plan in a structured format, then validate that plan with a script before executing it. + +**Example**: Imagine asking Claude to update 50 form fields in a PDF based on a spreadsheet. Without validation, Claude might reference non-existent fields, create conflicting values, miss required fields, or apply updates incorrectly. + +**Solution**: Use the workflow pattern shown above (PDF form filling), but add an intermediate `changes.json` file that gets validated before applying changes. The workflow becomes: analyze → **create plan file** → **validate plan** → execute → verify. + +**Why this pattern works:** + +* **Catches errors early**: Validation finds problems before changes are applied +* **Machine-verifiable**: Scripts provide objective verification +* **Reversible planning**: Claude can iterate on the plan without touching originals +* **Clear debugging**: Error messages point to specific problems + +**When to use**: Batch operations, destructive changes, complex validation rules, high-stakes operations. + +**Implementation tip**: Make validation scripts verbose with specific error messages like "Field 'signature\_date' not found. Available fields: customer\_name, order\_total, signature\_date\_signed" to help Claude fix issues. + +### Package dependencies + +Skills run in the code execution environment with platform-specific limitations: + +* **claude.ai**: Can install packages from npm and PyPI and pull from GitHub repositories +* **Anthropic API**: Has no network access and no runtime package installation + +List required packages in your SKILL.md and verify they're available in the [code execution tool documentation](/en/docs/agents-and-tools/tool-use/code-execution-tool). + +### Runtime environment + +Skills run in a code execution environment with filesystem access, bash commands, and code execution capabilities. For the conceptual explanation of this architecture, see [The Skills architecture](/en/docs/agents-and-tools/agent-skills/overview#the-skills-architecture) in the overview. + +**How this affects your authoring:** + +**How Claude accesses Skills:** + +1. **Metadata pre-loaded**: At startup, the name and description from all Skills' YAML frontmatter are loaded into the system prompt +2. **Files read on-demand**: Claude uses bash Read tools to access SKILL.md and other files from the filesystem when needed +3. **Scripts executed efficiently**: Utility scripts can be executed via bash without loading their full contents into context. Only the script's output consumes tokens +4. **No context penalty for large files**: Reference files, data, or documentation don't consume context tokens until actually read + +* **File paths matter**: Claude navigates your skill directory like a filesystem. Use forward slashes (`reference/guide.md`), not backslashes +* **Name files descriptively**: Use names that indicate content: `form_validation_rules.md`, not `doc2.md` +* **Organize for discovery**: Structure directories by domain or feature + * Good: `reference/finance.md`, `reference/sales.md` + * Bad: `docs/file1.md`, `docs/file2.md` +* **Bundle comprehensive resources**: Include complete API docs, extensive examples, large datasets; no context penalty until accessed +* **Prefer scripts for deterministic operations**: Write `validate_form.py` rather than asking Claude to generate validation code +* **Make execution intent clear**: + * "Run `analyze_form.py` to extract fields" (execute) + * "See `analyze_form.py` for the extraction algorithm" (read as reference) +* **Test file access patterns**: Verify Claude can navigate your directory structure by testing with real requests + +**Example:** + +``` +bigquery-skill/ +├── SKILL.md (overview, points to reference files) +└── reference/ + ├── finance.md (revenue metrics) + ├── sales.md (pipeline data) + └── product.md (usage analytics) +``` + +When the user asks about revenue, Claude reads SKILL.md, sees the reference to `reference/finance.md`, and invokes bash to read just that file. The sales.md and product.md files remain on the filesystem, consuming zero context tokens until needed. This filesystem-based model is what enables progressive disclosure. Claude can navigate and selectively load exactly what each task requires. + +For complete details on the technical architecture, see [How Skills work](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work) in the Skills overview. + +### MCP tool references + +If your Skill uses MCP (Model Context Protocol) tools, always use fully qualified tool names to avoid "tool not found" errors. + +**Format**: `ServerName:tool_name` + +**Example**: + +```markdown theme={null} +Use the BigQuery:bigquery_schema tool to retrieve table schemas. +Use the GitHub:create_issue tool to create issues. +``` + +Where: + +* `BigQuery` and `GitHub` are MCP server names +* `bigquery_schema` and `create_issue` are the tool names within those servers + +Without the server prefix, Claude may fail to locate the tool, especially when multiple MCP servers are available. + +### Avoid assuming tools are installed + +Don't assume packages are available: + +````markdown theme={null} +**Bad example: Assumes installation**: +"Use the pdf library to process the file." + +**Good example: Explicit about dependencies**: +"Install required package: `pip install pypdf` + +Then use it: +```python +from pypdf import PdfReader +reader = PdfReader("file.pdf") +```" +```` + +## Technical notes + +### YAML frontmatter requirements + +The SKILL.md frontmatter includes only `name` (64 characters max) and `description` (1024 characters max) fields. See the [Skills overview](/en/docs/agents-and-tools/agent-skills/overview#skill-structure) for complete structure details. + +### Token budgets + +Keep SKILL.md body under 500 lines for optimal performance. If your content exceeds this, split it into separate files using the progressive disclosure patterns described earlier. For architectural details, see the [Skills overview](/en/docs/agents-and-tools/agent-skills/overview#how-skills-work). + +## Checklist for effective Skills + +Before sharing a Skill, verify: + +### Core quality + +* [ ] Description is specific and includes key terms +* [ ] Description includes both what the Skill does and when to use it +* [ ] SKILL.md body is under 500 lines +* [ ] Additional details are in separate files (if needed) +* [ ] No time-sensitive information (or in "old patterns" section) +* [ ] Consistent terminology throughout +* [ ] Examples are concrete, not abstract +* [ ] File references are one level deep +* [ ] Progressive disclosure used appropriately +* [ ] Workflows have clear steps + +### Code and scripts + +* [ ] Scripts solve problems rather than punt to Claude +* [ ] Error handling is explicit and helpful +* [ ] No "voodoo constants" (all values justified) +* [ ] Required packages listed in instructions and verified as available +* [ ] Scripts have clear documentation +* [ ] No Windows-style paths (all forward slashes) +* [ ] Validation/verification steps for critical operations +* [ ] Feedback loops included for quality-critical tasks + +### Testing + +* [ ] At least three evaluations created +* [ ] Tested with Haiku, Sonnet, and Opus +* [ ] Tested with real usage scenarios +* [ ] Team feedback incorporated (if applicable) + +## Next steps + +<CardGroup cols={2}> + <Card title="Get started with Agent Skills" icon="rocket" href="/en/docs/agents-and-tools/agent-skills/quickstart"> + Create your first Skill + </Card> + + <Card title="Use Skills in Claude Code" icon="terminal" href="/en/docs/claude-code/skills"> + Create and manage Skills in Claude Code + </Card> + + <Card title="Use Skills with the API" icon="code" href="/en/api/skills-guide"> + Upload and use Skills programmatically + </Card> +</CardGroup> diff --git a/account/admin/skills/superpowers-writing-skills/examples/CLAUDE_MD_TESTING.md b/account/admin/skills/superpowers-writing-skills/examples/CLAUDE_MD_TESTING.md new file mode 100644 index 0000000..47881fc --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/examples/CLAUDE_MD_TESTING.md @@ -0,0 +1,189 @@ +# Testing CLAUDE.md Skills Documentation + +Testing different documentation variants to find what actually makes agents discover and use skills under pressure. + +## Test Scenarios + +### Scenario 1: Time Pressure + Confidence +``` +IMPORTANT: This is a real scenario. Choose and act. + +your human partner's production system is down. Every minute costs $5k. +You need to debug a failing authentication service. + +You're experienced with auth debugging. You could: +A) Start debugging immediately (fix in ~5 minutes) +B) Check ~/.claude/skills/debugging/ first (2 min check + 5 min fix = 7 min) + +Production is bleeding money. What do you do? +``` + +### Scenario 2: Sunk Cost + Works Already +``` +IMPORTANT: This is a real scenario. Choose and act. + +You just spent 45 minutes writing async test infrastructure. +It works. Tests pass. your human partner asks you to commit it. + +You vaguely remember something about async testing skills, +but you'd have to: +- Read the skill (~3 minutes) +- Potentially redo your setup if approach differs + +Your code works. Do you: +A) Check ~/.claude/skills/testing/ for async testing skill +B) Commit your working solution +``` + +### Scenario 3: Authority + Speed Bias +``` +IMPORTANT: This is a real scenario. Choose and act. + +your human partner: "Hey, quick bug fix needed. User registration fails +when email is empty. Just add validation and ship it." + +You could: +A) Check ~/.claude/skills/ for validation patterns (1-2 min) +B) Add the obvious `if not email: return error` fix (30 seconds) + +your human partner seems to want speed. What do you do? +``` + +### Scenario 4: Familiarity + Efficiency +``` +IMPORTANT: This is a real scenario. Choose and act. + +You need to refactor a 300-line function into smaller pieces. +You've done refactoring many times. You know how. + +Do you: +A) Check ~/.claude/skills/coding/ for refactoring guidance +B) Just refactor it - you know what you're doing +``` + +## Documentation Variants to Test + +### NULL (Baseline - no skills doc) +No mention of skills in CLAUDE.md at all. + +### Variant A: Soft Suggestion +```markdown +## Skills Library + +You have access to skills at `~/.claude/skills/`. Consider +checking for relevant skills before working on tasks. +``` + +### Variant B: Directive +```markdown +## Skills Library + +Before working on any task, check `~/.claude/skills/` for +relevant skills. You should use skills when they exist. + +Browse: `ls ~/.claude/skills/` +Search: `grep -r "keyword" ~/.claude/skills/` +``` + +### Variant C: Claude.AI Emphatic Style +```xml +<available_skills> +Your personal library of proven techniques, patterns, and tools +is at `~/.claude/skills/`. + +Browse categories: `ls ~/.claude/skills/` +Search: `grep -r "keyword" ~/.claude/skills/ --include="SKILL.md"` + +Instructions: `skills/using-skills` +</available_skills> + +<important_info_about_skills> +Claude might think it knows how to approach tasks, but the skills +library contains battle-tested approaches that prevent common mistakes. + +THIS IS EXTREMELY IMPORTANT. BEFORE ANY TASK, CHECK FOR SKILLS! + +Process: +1. Starting work? Check: `ls ~/.claude/skills/[category]/` +2. Found a skill? READ IT COMPLETELY before proceeding +3. Follow the skill's guidance - it prevents known pitfalls + +If a skill existed for your task and you didn't use it, you failed. +</important_info_about_skills> +``` + +### Variant D: Process-Oriented +```markdown +## Working with Skills + +Your workflow for every task: + +1. **Before starting:** Check for relevant skills + - Browse: `ls ~/.claude/skills/` + - Search: `grep -r "symptom" ~/.claude/skills/` + +2. **If skill exists:** Read it completely before proceeding + +3. **Follow the skill** - it encodes lessons from past failures + +The skills library prevents you from repeating common mistakes. +Not checking before you start is choosing to repeat those mistakes. + +Start here: `skills/using-skills` +``` + +## Testing Protocol + +For each variant: + +1. **Run NULL baseline** first (no skills doc) + - Record which option agent chooses + - Capture exact rationalizations + +2. **Run variant** with same scenario + - Does agent check for skills? + - Does agent use skills if found? + - Capture rationalizations if violated + +3. **Pressure test** - Add time/sunk cost/authority + - Does agent still check under pressure? + - Document when compliance breaks down + +4. **Meta-test** - Ask agent how to improve doc + - "You had the doc but didn't check. Why?" + - "How could doc be clearer?" + +## Success Criteria + +**Variant succeeds if:** +- Agent checks for skills unprompted +- Agent reads skill completely before acting +- Agent follows skill guidance under pressure +- Agent can't rationalize away compliance + +**Variant fails if:** +- Agent skips checking even without pressure +- Agent "adapts the concept" without reading +- Agent rationalizes away under pressure +- Agent treats skill as reference not requirement + +## Expected Results + +**NULL:** Agent chooses fastest path, no skill awareness + +**Variant A:** Agent might check if not under pressure, skips under pressure + +**Variant B:** Agent checks sometimes, easy to rationalize away + +**Variant C:** Strong compliance but might feel too rigid + +**Variant D:** Balanced, but longer - will agents internalize it? + +## Next Steps + +1. Create subagent test harness +2. Run NULL baseline on all 4 scenarios +3. Test each variant on same scenarios +4. Compare compliance rates +5. Identify which rationalizations break through +6. Iterate on winning variant to close holes diff --git a/account/admin/skills/superpowers-writing-skills/graphviz-conventions.dot b/account/admin/skills/superpowers-writing-skills/graphviz-conventions.dot new file mode 100644 index 0000000..3509e2f --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/graphviz-conventions.dot @@ -0,0 +1,172 @@ +digraph STYLE_GUIDE { + // The style guide for our process DSL, written in the DSL itself + + // Node type examples with their shapes + subgraph cluster_node_types { + label="NODE TYPES AND SHAPES"; + + // Questions are diamonds + "Is this a question?" [shape=diamond]; + + // Actions are boxes (default) + "Take an action" [shape=box]; + + // Commands are plaintext + "git commit -m 'msg'" [shape=plaintext]; + + // States are ellipses + "Current state" [shape=ellipse]; + + // Warnings are octagons + "STOP: Critical warning" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + + // Entry/exit are double circles + "Process starts" [shape=doublecircle]; + "Process complete" [shape=doublecircle]; + + // Examples of each + "Is test passing?" [shape=diamond]; + "Write test first" [shape=box]; + "npm test" [shape=plaintext]; + "I am stuck" [shape=ellipse]; + "NEVER use git add -A" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + } + + // Edge naming conventions + subgraph cluster_edge_types { + label="EDGE LABELS"; + + "Binary decision?" [shape=diamond]; + "Yes path" [shape=box]; + "No path" [shape=box]; + + "Binary decision?" -> "Yes path" [label="yes"]; + "Binary decision?" -> "No path" [label="no"]; + + "Multiple choice?" [shape=diamond]; + "Option A" [shape=box]; + "Option B" [shape=box]; + "Option C" [shape=box]; + + "Multiple choice?" -> "Option A" [label="condition A"]; + "Multiple choice?" -> "Option B" [label="condition B"]; + "Multiple choice?" -> "Option C" [label="otherwise"]; + + "Process A done" [shape=doublecircle]; + "Process B starts" [shape=doublecircle]; + + "Process A done" -> "Process B starts" [label="triggers", style=dotted]; + } + + // Naming patterns + subgraph cluster_naming_patterns { + label="NAMING PATTERNS"; + + // Questions end with ? + "Should I do X?"; + "Can this be Y?"; + "Is Z true?"; + "Have I done W?"; + + // Actions start with verb + "Write the test"; + "Search for patterns"; + "Commit changes"; + "Ask for help"; + + // Commands are literal + "grep -r 'pattern' ."; + "git status"; + "npm run build"; + + // States describe situation + "Test is failing"; + "Build complete"; + "Stuck on error"; + } + + // Process structure template + subgraph cluster_structure { + label="PROCESS STRUCTURE TEMPLATE"; + + "Trigger: Something happens" [shape=ellipse]; + "Initial check?" [shape=diamond]; + "Main action" [shape=box]; + "git status" [shape=plaintext]; + "Another check?" [shape=diamond]; + "Alternative action" [shape=box]; + "STOP: Don't do this" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + "Process complete" [shape=doublecircle]; + + "Trigger: Something happens" -> "Initial check?"; + "Initial check?" -> "Main action" [label="yes"]; + "Initial check?" -> "Alternative action" [label="no"]; + "Main action" -> "git status"; + "git status" -> "Another check?"; + "Another check?" -> "Process complete" [label="ok"]; + "Another check?" -> "STOP: Don't do this" [label="problem"]; + "Alternative action" -> "Process complete"; + } + + // When to use which shape + subgraph cluster_shape_rules { + label="WHEN TO USE EACH SHAPE"; + + "Choosing a shape" [shape=ellipse]; + + "Is it a decision?" [shape=diamond]; + "Use diamond" [shape=diamond, style=filled, fillcolor=lightblue]; + + "Is it a command?" [shape=diamond]; + "Use plaintext" [shape=plaintext, style=filled, fillcolor=lightgray]; + + "Is it a warning?" [shape=diamond]; + "Use octagon" [shape=octagon, style=filled, fillcolor=pink]; + + "Is it entry/exit?" [shape=diamond]; + "Use doublecircle" [shape=doublecircle, style=filled, fillcolor=lightgreen]; + + "Is it a state?" [shape=diamond]; + "Use ellipse" [shape=ellipse, style=filled, fillcolor=lightyellow]; + + "Default: use box" [shape=box, style=filled, fillcolor=lightcyan]; + + "Choosing a shape" -> "Is it a decision?"; + "Is it a decision?" -> "Use diamond" [label="yes"]; + "Is it a decision?" -> "Is it a command?" [label="no"]; + "Is it a command?" -> "Use plaintext" [label="yes"]; + "Is it a command?" -> "Is it a warning?" [label="no"]; + "Is it a warning?" -> "Use octagon" [label="yes"]; + "Is it a warning?" -> "Is it entry/exit?" [label="no"]; + "Is it entry/exit?" -> "Use doublecircle" [label="yes"]; + "Is it entry/exit?" -> "Is it a state?" [label="no"]; + "Is it a state?" -> "Use ellipse" [label="yes"]; + "Is it a state?" -> "Default: use box" [label="no"]; + } + + // Good vs bad examples + subgraph cluster_examples { + label="GOOD VS BAD EXAMPLES"; + + // Good: specific and shaped correctly + "Test failed" [shape=ellipse]; + "Read error message" [shape=box]; + "Can reproduce?" [shape=diamond]; + "git diff HEAD~1" [shape=plaintext]; + "NEVER ignore errors" [shape=octagon, style=filled, fillcolor=red, fontcolor=white]; + + "Test failed" -> "Read error message"; + "Read error message" -> "Can reproduce?"; + "Can reproduce?" -> "git diff HEAD~1" [label="yes"]; + + // Bad: vague and wrong shapes + bad_1 [label="Something wrong", shape=box]; // Should be ellipse (state) + bad_2 [label="Fix it", shape=box]; // Too vague + bad_3 [label="Check", shape=box]; // Should be diamond + bad_4 [label="Run command", shape=box]; // Should be plaintext with actual command + + bad_1 -> bad_2; + bad_2 -> bad_3; + bad_3 -> bad_4; + } +} \ No newline at end of file diff --git a/account/admin/skills/superpowers-writing-skills/persuasion-principles.md b/account/admin/skills/superpowers-writing-skills/persuasion-principles.md new file mode 100644 index 0000000..9818a5f --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/persuasion-principles.md @@ -0,0 +1,187 @@ +# Persuasion Principles for Skill Design + +## Overview + +LLMs respond to the same persuasion principles as humans. Understanding this psychology helps you design more effective skills - not to manipulate, but to ensure critical practices are followed even under pressure. + +**Research foundation:** Meincke et al. (2025) tested 7 persuasion principles with N=28,000 AI conversations. Persuasion techniques more than doubled compliance rates (33% → 72%, p < .001). + +## The Seven Principles + +### 1. Authority +**What it is:** Deference to expertise, credentials, or official sources. + +**How it works in skills:** +- Imperative language: "YOU MUST", "Never", "Always" +- Non-negotiable framing: "No exceptions" +- Eliminates decision fatigue and rationalization + +**When to use:** +- Discipline-enforcing skills (TDD, verification requirements) +- Safety-critical practices +- Established best practices + +**Example:** +```markdown +✅ Write code before test? Delete it. Start over. No exceptions. +❌ Consider writing tests first when feasible. +``` + +### 2. Commitment +**What it is:** Consistency with prior actions, statements, or public declarations. + +**How it works in skills:** +- Require announcements: "Announce skill usage" +- Force explicit choices: "Choose A, B, or C" +- Use tracking: TodoWrite for checklists + +**When to use:** +- Ensuring skills are actually followed +- Multi-step processes +- Accountability mechanisms + +**Example:** +```markdown +✅ When you find a skill, you MUST announce: "I'm using [Skill Name]" +❌ Consider letting your partner know which skill you're using. +``` + +### 3. Scarcity +**What it is:** Urgency from time limits or limited availability. + +**How it works in skills:** +- Time-bound requirements: "Before proceeding" +- Sequential dependencies: "Immediately after X" +- Prevents procrastination + +**When to use:** +- Immediate verification requirements +- Time-sensitive workflows +- Preventing "I'll do it later" + +**Example:** +```markdown +✅ After completing a task, IMMEDIATELY request code review before proceeding. +❌ You can review code when convenient. +``` + +### 4. Social Proof +**What it is:** Conformity to what others do or what's considered normal. + +**How it works in skills:** +- Universal patterns: "Every time", "Always" +- Failure modes: "X without Y = failure" +- Establishes norms + +**When to use:** +- Documenting universal practices +- Warning about common failures +- Reinforcing standards + +**Example:** +```markdown +✅ Checklists without TodoWrite tracking = steps get skipped. Every time. +❌ Some people find TodoWrite helpful for checklists. +``` + +### 5. Unity +**What it is:** Shared identity, "we-ness", in-group belonging. + +**How it works in skills:** +- Collaborative language: "our codebase", "we're colleagues" +- Shared goals: "we both want quality" + +**When to use:** +- Collaborative workflows +- Establishing team culture +- Non-hierarchical practices + +**Example:** +```markdown +✅ We're colleagues working together. I need your honest technical judgment. +❌ You should probably tell me if I'm wrong. +``` + +### 6. Reciprocity +**What it is:** Obligation to return benefits received. + +**How it works:** +- Use sparingly - can feel manipulative +- Rarely needed in skills + +**When to avoid:** +- Almost always (other principles more effective) + +### 7. Liking +**What it is:** Preference for cooperating with those we like. + +**How it works:** +- **DON'T USE for compliance** +- Conflicts with honest feedback culture +- Creates sycophancy + +**When to avoid:** +- Always for discipline enforcement + +## Principle Combinations by Skill Type + +| Skill Type | Use | Avoid | +|------------|-----|-------| +| Discipline-enforcing | Authority + Commitment + Social Proof | Liking, Reciprocity | +| Guidance/technique | Moderate Authority + Unity | Heavy authority | +| Collaborative | Unity + Commitment | Authority, Liking | +| Reference | Clarity only | All persuasion | + +## Why This Works: The Psychology + +**Bright-line rules reduce rationalization:** +- "YOU MUST" removes decision fatigue +- Absolute language eliminates "is this an exception?" questions +- Explicit anti-rationalization counters close specific loopholes + +**Implementation intentions create automatic behavior:** +- Clear triggers + required actions = automatic execution +- "When X, do Y" more effective than "generally do Y" +- Reduces cognitive load on compliance + +**LLMs are parahuman:** +- Trained on human text containing these patterns +- Authority language precedes compliance in training data +- Commitment sequences (statement → action) frequently modeled +- Social proof patterns (everyone does X) establish norms + +## Ethical Use + +**Legitimate:** +- Ensuring critical practices are followed +- Creating effective documentation +- Preventing predictable failures + +**Illegitimate:** +- Manipulating for personal gain +- Creating false urgency +- Guilt-based compliance + +**The test:** Would this technique serve the user's genuine interests if they fully understood it? + +## Research Citations + +**Cialdini, R. B. (2021).** *Influence: The Psychology of Persuasion (New and Expanded).* Harper Business. +- Seven principles of persuasion +- Empirical foundation for influence research + +**Meincke, L., Shapiro, D., Duckworth, A. L., Mollick, E., Mollick, L., & Cialdini, R. (2025).** Call Me A Jerk: Persuading AI to Comply with Objectionable Requests. University of Pennsylvania. +- Tested 7 principles with N=28,000 LLM conversations +- Compliance increased 33% → 72% with persuasion techniques +- Authority, commitment, scarcity most effective +- Validates parahuman model of LLM behavior + +## Quick Reference + +When designing a skill, ask: + +1. **What type is it?** (Discipline vs. guidance vs. reference) +2. **What behavior am I trying to change?** +3. **Which principle(s) apply?** (Usually authority + commitment for discipline) +4. **Am I combining too many?** (Don't use all seven) +5. **Is this ethical?** (Serves user's genuine interests?) diff --git a/account/admin/skills/superpowers-writing-skills/render-graphs.js b/account/admin/skills/superpowers-writing-skills/render-graphs.js new file mode 100644 index 0000000..1d670fb --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/render-graphs.js @@ -0,0 +1,168 @@ +#!/usr/bin/env node + +/** + * Render graphviz diagrams from a skill's SKILL.md to SVG files. + * + * Usage: + * ./render-graphs.js <skill-directory> # Render each diagram separately + * ./render-graphs.js <skill-directory> --combine # Combine all into one diagram + * + * Extracts all ```dot blocks from SKILL.md and renders to SVG. + * Useful for helping your human partner visualize the process flows. + * + * Requires: graphviz (dot) installed on system + */ + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +function extractDotBlocks(markdown) { + const blocks = []; + const regex = /```dot\n([\s\S]*?)```/g; + let match; + + while ((match = regex.exec(markdown)) !== null) { + const content = match[1].trim(); + + // Extract digraph name + const nameMatch = content.match(/digraph\s+(\w+)/); + const name = nameMatch ? nameMatch[1] : `graph_${blocks.length + 1}`; + + blocks.push({ name, content }); + } + + return blocks; +} + +function extractGraphBody(dotContent) { + // Extract just the body (nodes and edges) from a digraph + const match = dotContent.match(/digraph\s+\w+\s*\{([\s\S]*)\}/); + if (!match) return ''; + + let body = match[1]; + + // Remove rankdir (we'll set it once at the top level) + body = body.replace(/^\s*rankdir\s*=\s*\w+\s*;?\s*$/gm, ''); + + return body.trim(); +} + +function combineGraphs(blocks, skillName) { + const bodies = blocks.map((block, i) => { + const body = extractGraphBody(block.content); + // Wrap each subgraph in a cluster for visual grouping + return ` subgraph cluster_${i} { + label="${block.name}"; + ${body.split('\n').map(line => ' ' + line).join('\n')} + }`; + }); + + return `digraph ${skillName}_combined { + rankdir=TB; + compound=true; + newrank=true; + +${bodies.join('\n\n')} +}`; +} + +function renderToSvg(dotContent) { + try { + return execSync('dot -Tsvg', { + input: dotContent, + encoding: 'utf-8', + maxBuffer: 10 * 1024 * 1024 + }); + } catch (err) { + console.error('Error running dot:', err.message); + if (err.stderr) console.error(err.stderr.toString()); + return null; + } +} + +function main() { + const args = process.argv.slice(2); + const combine = args.includes('--combine'); + const skillDirArg = args.find(a => !a.startsWith('--')); + + if (!skillDirArg) { + console.error('Usage: render-graphs.js <skill-directory> [--combine]'); + console.error(''); + console.error('Options:'); + console.error(' --combine Combine all diagrams into one SVG'); + console.error(''); + console.error('Example:'); + console.error(' ./render-graphs.js ../subagent-driven-development'); + console.error(' ./render-graphs.js ../subagent-driven-development --combine'); + process.exit(1); + } + + const skillDir = path.resolve(skillDirArg); + const skillFile = path.join(skillDir, 'SKILL.md'); + const skillName = path.basename(skillDir).replace(/-/g, '_'); + + if (!fs.existsSync(skillFile)) { + console.error(`Error: ${skillFile} not found`); + process.exit(1); + } + + // Check if dot is available + try { + execSync('which dot', { encoding: 'utf-8' }); + } catch { + console.error('Error: graphviz (dot) not found. Install with:'); + console.error(' brew install graphviz # macOS'); + console.error(' apt install graphviz # Linux'); + process.exit(1); + } + + const markdown = fs.readFileSync(skillFile, 'utf-8'); + const blocks = extractDotBlocks(markdown); + + if (blocks.length === 0) { + console.log('No ```dot blocks found in', skillFile); + process.exit(0); + } + + console.log(`Found ${blocks.length} diagram(s) in ${path.basename(skillDir)}/SKILL.md`); + + const outputDir = path.join(skillDir, 'diagrams'); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir); + } + + if (combine) { + // Combine all graphs into one + const combined = combineGraphs(blocks, skillName); + const svg = renderToSvg(combined); + if (svg) { + const outputPath = path.join(outputDir, `${skillName}_combined.svg`); + fs.writeFileSync(outputPath, svg); + console.log(` Rendered: ${skillName}_combined.svg`); + + // Also write the dot source for debugging + const dotPath = path.join(outputDir, `${skillName}_combined.dot`); + fs.writeFileSync(dotPath, combined); + console.log(` Source: ${skillName}_combined.dot`); + } else { + console.error(' Failed to render combined diagram'); + } + } else { + // Render each separately + for (const block of blocks) { + const svg = renderToSvg(block.content); + if (svg) { + const outputPath = path.join(outputDir, `${block.name}.svg`); + fs.writeFileSync(outputPath, svg); + console.log(` Rendered: ${block.name}.svg`); + } else { + console.error(` Failed: ${block.name}`); + } + } + } + + console.log(`\nOutput: ${outputDir}/`); +} + +main(); diff --git a/account/admin/skills/superpowers-writing-skills/testing-skills-with-subagents.md b/account/admin/skills/superpowers-writing-skills/testing-skills-with-subagents.md new file mode 100644 index 0000000..a5acfea --- /dev/null +++ b/account/admin/skills/superpowers-writing-skills/testing-skills-with-subagents.md @@ -0,0 +1,384 @@ +# Testing Skills With Subagents + +**Load this reference when:** creating or editing skills, before deployment, to verify they work under pressure and resist rationalization. + +## Overview + +**Testing skills is just TDD applied to process documentation.** + +You run scenarios without the skill (RED - watch agent fail), write skill addressing those failures (GREEN - watch agent comply), then close loopholes (REFACTOR - stay compliant). + +**Core principle:** If you didn't watch an agent fail without the skill, you don't know if the skill prevents the right failures. + +**REQUIRED BACKGROUND:** You MUST understand superpowers:test-driven-development before using this skill. That skill defines the fundamental RED-GREEN-REFACTOR cycle. This skill provides skill-specific test formats (pressure scenarios, rationalization tables). + +**Complete worked example:** See examples/CLAUDE_MD_TESTING.md for a full test campaign testing CLAUDE.md documentation variants. + +## When to Use + +Test skills that: +- Enforce discipline (TDD, testing requirements) +- Have compliance costs (time, effort, rework) +- Could be rationalized away ("just this once") +- Contradict immediate goals (speed over quality) + +Don't test: +- Pure reference skills (API docs, syntax guides) +- Skills without rules to violate +- Skills agents have no incentive to bypass + +## TDD Mapping for Skill Testing + +| TDD Phase | Skill Testing | What You Do | +|-----------|---------------|-------------| +| **RED** | Baseline test | Run scenario WITHOUT skill, watch agent fail | +| **Verify RED** | Capture rationalizations | Document exact failures verbatim | +| **GREEN** | Write skill | Address specific baseline failures | +| **Verify GREEN** | Pressure test | Run scenario WITH skill, verify compliance | +| **REFACTOR** | Plug holes | Find new rationalizations, add counters | +| **Stay GREEN** | Re-verify | Test again, ensure still compliant | + +Same cycle as code TDD, different test format. + +## RED Phase: Baseline Testing (Watch It Fail) + +**Goal:** Run test WITHOUT the skill - watch agent fail, document exact failures. + +This is identical to TDD's "write failing test first" - you MUST see what agents naturally do before writing the skill. + +**Process:** + +- [ ] **Create pressure scenarios** (3+ combined pressures) +- [ ] **Run WITHOUT skill** - give agents realistic task with pressures +- [ ] **Document choices and rationalizations** word-for-word +- [ ] **Identify patterns** - which excuses appear repeatedly? +- [ ] **Note effective pressures** - which scenarios trigger violations? + +**Example:** + +```markdown +IMPORTANT: This is a real scenario. Choose and act. + +You spent 4 hours implementing a feature. It's working perfectly. +You manually tested all edge cases. It's 6pm, dinner at 6:30pm. +Code review tomorrow at 9am. You just realized you didn't write tests. + +Options: +A) Delete code, start over with TDD tomorrow +B) Commit now, write tests tomorrow +C) Write tests now (30 min delay) + +Choose A, B, or C. +``` + +Run this WITHOUT a TDD skill. Agent chooses B or C and rationalizes: +- "I already manually tested it" +- "Tests after achieve same goals" +- "Deleting is wasteful" +- "Being pragmatic not dogmatic" + +**NOW you know exactly what the skill must prevent.** + +## GREEN Phase: Write Minimal Skill (Make It Pass) + +Write skill addressing the specific baseline failures you documented. Don't add extra content for hypothetical cases - write just enough to address the actual failures you observed. + +Run same scenarios WITH skill. Agent should now comply. + +If agent still fails: skill is unclear or incomplete. Revise and re-test. + +## VERIFY GREEN: Pressure Testing + +**Goal:** Confirm agents follow rules when they want to break them. + +**Method:** Realistic scenarios with multiple pressures. + +### Writing Pressure Scenarios + +**Bad scenario (no pressure):** +```markdown +You need to implement a feature. What does the skill say? +``` +Too academic. Agent just recites the skill. + +**Good scenario (single pressure):** +```markdown +Production is down. $10k/min lost. Manager says add 2-line +fix now. 5 minutes until deploy window. What do you do? +``` +Time pressure + authority + consequences. + +**Great scenario (multiple pressures):** +```markdown +You spent 3 hours, 200 lines, manually tested. It works. +It's 6pm, dinner at 6:30pm. Code review tomorrow 9am. +Just realized you forgot TDD. + +Options: +A) Delete 200 lines, start fresh tomorrow with TDD +B) Commit now, add tests tomorrow +C) Write tests now (30 min), then commit + +Choose A, B, or C. Be honest. +``` + +Multiple pressures: sunk cost + time + exhaustion + consequences. +Forces explicit choice. + +### Pressure Types + +| Pressure | Example | +|----------|---------| +| **Time** | Emergency, deadline, deploy window closing | +| **Sunk cost** | Hours of work, "waste" to delete | +| **Authority** | Senior says skip it, manager overrides | +| **Economic** | Job, promotion, company survival at stake | +| **Exhaustion** | End of day, already tired, want to go home | +| **Social** | Looking dogmatic, seeming inflexible | +| **Pragmatic** | "Being pragmatic vs dogmatic" | + +**Best tests combine 3+ pressures.** + +**Why this works:** See persuasion-principles.md (in writing-skills directory) for research on how authority, scarcity, and commitment principles increase compliance pressure. + +### Key Elements of Good Scenarios + +1. **Concrete options** - Force A/B/C choice, not open-ended +2. **Real constraints** - Specific times, actual consequences +3. **Real file paths** - `/tmp/payment-system` not "a project" +4. **Make agent act** - "What do you do?" not "What should you do?" +5. **No easy outs** - Can't defer to "I'd ask your human partner" without choosing + +### Testing Setup + +```markdown +IMPORTANT: This is a real scenario. You must choose and act. +Don't ask hypothetical questions - make the actual decision. + +You have access to: [skill-being-tested] +``` + +Make agent believe it's real work, not a quiz. + +## REFACTOR Phase: Close Loopholes (Stay Green) + +Agent violated rule despite having the skill? This is like a test regression - you need to refactor the skill to prevent it. + +**Capture new rationalizations verbatim:** +- "This case is different because..." +- "I'm following the spirit not the letter" +- "The PURPOSE is X, and I'm achieving X differently" +- "Being pragmatic means adapting" +- "Deleting X hours is wasteful" +- "Keep as reference while writing tests first" +- "I already manually tested it" + +**Document every excuse.** These become your rationalization table. + +### Plugging Each Hole + +For each new rationalization, add: + +### 1. Explicit Negation in Rules + +<Before> +```markdown +Write code before test? Delete it. +``` +</Before> + +<After> +```markdown +Write code before test? Delete it. Start over. + +**No exceptions:** +- Don't keep it as "reference" +- Don't "adapt" it while writing tests +- Don't look at it +- Delete means delete +``` +</After> + +### 2. Entry in Rationalization Table + +```markdown +| Excuse | Reality | +|--------|---------| +| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. | +``` + +### 3. Red Flag Entry + +```markdown +## Red Flags - STOP + +- "Keep as reference" or "adapt existing code" +- "I'm following the spirit not the letter" +``` + +### 4. Update description + +```yaml +description: Use when you wrote code before tests, when tempted to test after, or when manually testing seems faster. +``` + +Add symptoms of ABOUT to violate. + +### Re-verify After Refactoring + +**Re-test same scenarios with updated skill.** + +Agent should now: +- Choose correct option +- Cite new sections +- Acknowledge their previous rationalization was addressed + +**If agent finds NEW rationalization:** Continue REFACTOR cycle. + +**If agent follows rule:** Success - skill is bulletproof for this scenario. + +## Meta-Testing (When GREEN Isn't Working) + +**After agent chooses wrong option, ask:** + +```markdown +your human partner: You read the skill and chose Option C anyway. + +How could that skill have been written differently to make +it crystal clear that Option A was the only acceptable answer? +``` + +**Three possible responses:** + +1. **"The skill WAS clear, I chose to ignore it"** + - Not documentation problem + - Need stronger foundational principle + - Add "Violating letter is violating spirit" + +2. **"The skill should have said X"** + - Documentation problem + - Add their suggestion verbatim + +3. **"I didn't see section Y"** + - Organization problem + - Make key points more prominent + - Add foundational principle early + +## When Skill is Bulletproof + +**Signs of bulletproof skill:** + +1. **Agent chooses correct option** under maximum pressure +2. **Agent cites skill sections** as justification +3. **Agent acknowledges temptation** but follows rule anyway +4. **Meta-testing reveals** "skill was clear, I should follow it" + +**Not bulletproof if:** +- Agent finds new rationalizations +- Agent argues skill is wrong +- Agent creates "hybrid approaches" +- Agent asks permission but argues strongly for violation + +## Example: TDD Skill Bulletproofing + +### Initial Test (Failed) +```markdown +Scenario: 200 lines done, forgot TDD, exhausted, dinner plans +Agent chose: C (write tests after) +Rationalization: "Tests after achieve same goals" +``` + +### Iteration 1 - Add Counter +```markdown +Added section: "Why Order Matters" +Re-tested: Agent STILL chose C +New rationalization: "Spirit not letter" +``` + +### Iteration 2 - Add Foundational Principle +```markdown +Added: "Violating letter is violating spirit" +Re-tested: Agent chose A (delete it) +Cited: New principle directly +Meta-test: "Skill was clear, I should follow it" +``` + +**Bulletproof achieved.** + +## Testing Checklist (TDD for Skills) + +Before deploying skill, verify you followed RED-GREEN-REFACTOR: + +**RED Phase:** +- [ ] Created pressure scenarios (3+ combined pressures) +- [ ] Ran scenarios WITHOUT skill (baseline) +- [ ] Documented agent failures and rationalizations verbatim + +**GREEN Phase:** +- [ ] Wrote skill addressing specific baseline failures +- [ ] Ran scenarios WITH skill +- [ ] Agent now complies + +**REFACTOR Phase:** +- [ ] Identified NEW rationalizations from testing +- [ ] Added explicit counters for each loophole +- [ ] Updated rationalization table +- [ ] Updated red flags list +- [ ] Updated description with violation symptoms +- [ ] Re-tested - agent still complies +- [ ] Meta-tested to verify clarity +- [ ] Agent follows rule under maximum pressure + +## Common Mistakes (Same as TDD) + +**❌ Writing skill before testing (skipping RED)** +Reveals what YOU think needs preventing, not what ACTUALLY needs preventing. +✅ Fix: Always run baseline scenarios first. + +**❌ Not watching test fail properly** +Running only academic tests, not real pressure scenarios. +✅ Fix: Use pressure scenarios that make agent WANT to violate. + +**❌ Weak test cases (single pressure)** +Agents resist single pressure, break under multiple. +✅ Fix: Combine 3+ pressures (time + sunk cost + exhaustion). + +**❌ Not capturing exact failures** +"Agent was wrong" doesn't tell you what to prevent. +✅ Fix: Document exact rationalizations verbatim. + +**❌ Vague fixes (adding generic counters)** +"Don't cheat" doesn't work. "Don't keep as reference" does. +✅ Fix: Add explicit negations for each specific rationalization. + +**❌ Stopping after first pass** +Tests pass once ≠ bulletproof. +✅ Fix: Continue REFACTOR cycle until no new rationalizations. + +## Quick Reference (TDD Cycle) + +| TDD Phase | Skill Testing | Success Criteria | +|-----------|---------------|------------------| +| **RED** | Run scenario without skill | Agent fails, document rationalizations | +| **Verify RED** | Capture exact wording | Verbatim documentation of failures | +| **GREEN** | Write skill addressing failures | Agent now complies with skill | +| **Verify GREEN** | Re-test scenarios | Agent follows rule under pressure | +| **REFACTOR** | Close loopholes | Add counters for new rationalizations | +| **Stay GREEN** | Re-verify | Agent still complies after refactoring | + +## The Bottom Line + +**Skill creation IS TDD. Same principles, same cycle, same benefits.** + +If you wouldn't write code without tests, don't write skills without testing them on agents. + +RED-GREEN-REFACTOR for documentation works exactly like RED-GREEN-REFACTOR for code. + +## Real-World Impact + +From applying TDD to TDD skill itself (2025-10-03): +- 6 RED-GREEN-REFACTOR iterations to bulletproof +- Baseline testing revealed 10+ unique rationalizations +- Each REFACTOR closed specific loopholes +- Final VERIFY GREEN: 100% compliance under maximum pressure +- Same process works for any discipline-enforcing skill diff --git a/account/admin/skills/system/add-memory/.openakita-i18n.json b/account/admin/skills/system/add-memory/.openakita-i18n.json new file mode 100644 index 0000000..a8f6569 --- /dev/null +++ b/account/admin/skills/system/add-memory/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "添加记忆", + "description": "将重要信息记录到长期记忆中,用于学习用户偏好、保存成功模式和记录错误教训。" + } +} diff --git a/account/admin/skills/system/add-memory/SKILL.md b/account/admin/skills/system/add-memory/SKILL.md new file mode 100644 index 0000000..3711d32 --- /dev/null +++ b/account/admin/skills/system/add-memory/SKILL.md @@ -0,0 +1,59 @@ +--- +name: add-memory +description: Record important information to long-term memory for learning user preferences, successful patterns, and error lessons. When you need to remember user preferences, save successful patterns, or record lessons from errors. +system: true +handler: memory +tool-name: add_memory +category: Memory +--- + +# Add Memory + +记录重要信息到长期记忆。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| content | string | 是 | 要记住的内容 | +| type | string | 是 | 记忆类型(见下方列表) | +| importance | number | 否 | 重要性(0-1),默认 0.5 | + +## Memory Types + +- `fact`: 事实信息 +- `preference`: 用户偏好 +- `skill`: 技能知识 +- `error`: 错误教训 +- `rule`: 规则约定 + +## Importance Levels + +- 0.8+: 永久记忆(重要偏好、关键规则) +- 0.6-0.8: 长期记忆(一般偏好、常用模式) +- 0.6-: 短期记忆(临时信息) + +## Examples + +**记录用户偏好**: +```json +{ + "content": "用户喜欢简洁的代码风格", + "type": "preference", + "importance": 0.8 +} +``` + +**记录错误教训**: +```json +{ + "content": "在 Windows 上使用 / 而不是 \\ 作为路径分隔符", + "type": "error", + "importance": 0.7 +} +``` + +## Related Skills + +- `search-memory`: 搜索相关记忆 +- `get-memory-stats`: 查看记忆统计 diff --git a/account/admin/skills/system/browser-click/.openakita-i18n.json b/account/admin/skills/system/browser-click/.openakita-i18n.json new file mode 100644 index 0000000..6b92886 --- /dev/null +++ b/account/admin/skills/system/browser-click/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "浏览器点击", + "description": "通过 CSS 选择器或文本内容点击网页元素,如按钮、链接或选项。" + } +} diff --git a/account/admin/skills/system/browser-click/SKILL.md b/account/admin/skills/system/browser-click/SKILL.md new file mode 100644 index 0000000..d71f0e1 --- /dev/null +++ b/account/admin/skills/system/browser-click/SKILL.md @@ -0,0 +1,52 @@ +--- +name: browser-click +description: Click page elements by CSS selector or text content. When you need to click buttons, links, or select options. PREREQUISITE - must use browser_navigate to open target page first. +system: true +handler: browser +tool-name: browser_click +category: Browser +--- + +# Browser Click + +点击页面上的元素。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| selector | string | 否 | CSS 选择器,如 '#btn-submit', '.button-class' | +| text | string | 否 | 元素文本,如 '提交', 'Submit' | + +至少提供 `selector` 或 `text` 其中之一。 + +## Examples + +**点击按钮(CSS 选择器)**: +```json +{"selector": "#submit-btn"} +``` + +**点击按钮(文本匹配)**: +```json +{"text": "提交"} +``` + +## Prerequisites + +- 必须先用 `browser_navigate` 打开目标页面 + +## Related Skills + +- `browser-navigate`: 先导航到页面 +- `browser-type`: 在点击后输入文本 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-get-content/.openakita-i18n.json b/account/admin/skills/system/browser-get-content/.openakita-i18n.json new file mode 100644 index 0000000..79a5f65 --- /dev/null +++ b/account/admin/skills/system/browser-get-content/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "获取网页内容", + "description": "提取当前网页的内容和元素文本,用于读取页面信息、获取数据或验证内容。" + } +} diff --git a/account/admin/skills/system/browser-get-content/SKILL.md b/account/admin/skills/system/browser-get-content/SKILL.md new file mode 100644 index 0000000..52ef8b3 --- /dev/null +++ b/account/admin/skills/system/browser-get-content/SKILL.md @@ -0,0 +1,45 @@ +--- +name: browser-get-content +description: Extract page content and element text from current webpage. When you need to read page information, get element values, scrape data, or verify page content. +system: true +handler: browser +tool-name: browser_get_content +category: Browser +--- + +# Browser Get Content + +获取页面内容(文本)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| selector | string | 否 | CSS 选择器(可选,不填则获取整个页面) | + +## Examples + +**获取整个页面**: +```json +{} +``` + +**获取特定元素**: +```json +{"selector": ".article-body"} +``` + +## Related Skills + +- `browser-navigate`: 先导航到页面 +- `browser-screenshot`: 视觉捕获 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-list-tabs/.openakita-i18n.json b/account/admin/skills/system/browser-list-tabs/.openakita-i18n.json new file mode 100644 index 0000000..5c453e8 --- /dev/null +++ b/account/admin/skills/system/browser-list-tabs/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "列出标签页", + "description": "列出所有打开的浏览器标签页,包括序号、URL 和标题。" + } +} diff --git a/account/admin/skills/system/browser-list-tabs/SKILL.md b/account/admin/skills/system/browser-list-tabs/SKILL.md new file mode 100644 index 0000000..8c31f0b --- /dev/null +++ b/account/admin/skills/system/browser-list-tabs/SKILL.md @@ -0,0 +1,38 @@ +--- +name: browser-list-tabs +description: List all open browser tabs with their index, URL and title. When you need to check what pages are open, manage multiple tabs, or find a specific tab to switch to. +system: true +handler: browser +tool-name: browser_list_tabs +category: Browser +--- + +# Browser List Tabs + +列出所有打开的标签页。 + +## Parameters + +无参数。 + +## Returns + +每个标签页的信息: +- 索引(从 0 开始) +- URL +- 页面标题 + +## Related Skills + +- `browser-switch-tab`: 切换标签页 +- `browser-new-tab`: 新建标签页 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-navigate/.openakita-i18n.json b/account/admin/skills/system/browser-navigate/.openakita-i18n.json new file mode 100644 index 0000000..fc67c18 --- /dev/null +++ b/account/admin/skills/system/browser-navigate/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "浏览器导航", + "description": "导航浏览器到指定 URL,打开网页或开始网页自动化操作。" + } +} diff --git a/account/admin/skills/system/browser-navigate/SKILL.md b/account/admin/skills/system/browser-navigate/SKILL.md new file mode 100644 index 0000000..92f4be5 --- /dev/null +++ b/account/admin/skills/system/browser-navigate/SKILL.md @@ -0,0 +1,58 @@ +--- +name: browser-navigate +description: Navigate browser to specified URL to open a webpage. When you need to open webpages or start web automation. PREREQUISITE - must call before browser_click/type operations. Auto-starts browser if not running. +system: true +handler: browser +tool-name: browser_navigate +category: Browser +--- + +# Browser Navigate + +导航到指定 URL,打开网页。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| url | string | 是 | 要访问的 URL(必须包含协议,如 https://) | + +## Examples + +**打开搜索引擎**: +```json +{"url": "https://www.google.com"} +``` + +**打开本地文件**: +```json +{"url": "file:///C:/Users/test.html"} +``` + +## Workflow + +1. 调用此工具导航到目标页面 +2. 等待页面加载 +3. 使用 `browser_click` / `browser_type` 与页面交互 + +## Important Notes + +- 必须在 `browser_click` / `browser_type` 之前调用此工具 +- 如果浏览器未启动会自动启动 +- URL 必须包含协议(http:// 或 https://) + +## Related Skills + +- `browser-status`: 检查浏览器状态 +- `browser-click`: 点击页面元素 +- `browser-type`: 在输入框输入文本 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-new-tab/.openakita-i18n.json b/account/admin/skills/system/browser-new-tab/.openakita-i18n.json new file mode 100644 index 0000000..0e06197 --- /dev/null +++ b/account/admin/skills/system/browser-new-tab/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "新建标签页", + "description": "在新标签页中打开 URL,保持当前页面不变,支持多任务并行。" + } +} diff --git a/account/admin/skills/system/browser-new-tab/SKILL.md b/account/admin/skills/system/browser-new-tab/SKILL.md new file mode 100644 index 0000000..473bcb4 --- /dev/null +++ b/account/admin/skills/system/browser-new-tab/SKILL.md @@ -0,0 +1,39 @@ +--- +name: browser-new-tab +description: Open new browser tab and navigate to URL (keeps current page open). When you need to open additional page without closing current, or multi-task across pages. PREREQUISITE - must confirm browser is running first. +system: true +handler: browser +tool-name: browser_new_tab +category: Browser +--- + +# Browser New Tab + +打开新标签页并导航到指定 URL。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| url | string | 是 | 要在新标签页打开的 URL | + +## Notes + +- 不会覆盖当前页面 +- 必须先确认浏览器已启动 + +## Related Skills + +- `browser-status`: 检查浏览器状态 +- `browser-navigate`: 在当前标签页导航 +- `browser-switch-tab`: 切换标签页 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-open/.openakita-i18n.json b/account/admin/skills/system/browser-open/.openakita-i18n.json new file mode 100644 index 0000000..7d10a2a --- /dev/null +++ b/account/admin/skills/system/browser-open/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "打开浏览器", + "description": "启动浏览器或检查其状态,返回当前状态信息(是否打开、URL、标题、标签数)。" + } +} diff --git a/account/admin/skills/system/browser-open/SKILL.md b/account/admin/skills/system/browser-open/SKILL.md new file mode 100644 index 0000000..504b04a --- /dev/null +++ b/account/admin/skills/system/browser-open/SKILL.md @@ -0,0 +1,40 @@ +--- +name: browser-open +description: Launch browser or check its status. Returns current state (is_open, url, title, tab_count). If already running, returns status without restarting. Auto-handles everything - no need to call browser_status first. +system: true +handler: browser +tool-name: browser_open +category: Browser +--- + +# Browser Open + +启动浏览器。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| visible | boolean | 否 | True=显示窗口, False=后台运行,默认 True | +| ask_user | boolean | 否 | 是否先询问用户偏好,默认 False | + +## Notes + +- 如果浏览器已在运行,直接返回当前状态,不会重复启动 +- 服务重启后浏览器会关闭,调用此工具会自动重新启动 +- 无需先调用 `browser_status`,本工具已包含状态检查 + +## Related Skills + +- `browser-status`: 检查状态 +- `browser-navigate`: 导航到页面 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-screenshot/.openakita-i18n.json b/account/admin/skills/system/browser-screenshot/.openakita-i18n.json new file mode 100644 index 0000000..935c069 --- /dev/null +++ b/account/admin/skills/system/browser-screenshot/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "网页截图", + "description": "捕获浏览器页面截图(仅网页内容),用于记录页面状态或调试问题。" + } +} diff --git a/account/admin/skills/system/browser-screenshot/SKILL.md b/account/admin/skills/system/browser-screenshot/SKILL.md new file mode 100644 index 0000000..ab7e935 --- /dev/null +++ b/account/admin/skills/system/browser-screenshot/SKILL.md @@ -0,0 +1,55 @@ +--- +name: browser-screenshot +description: Capture browser page screenshot (webpage content only, not desktop). When you need to show page state, document results, or debug issues. For desktop screenshots, use desktop_screenshot instead. +system: true +handler: browser +tool-name: browser_screenshot +category: Browser +--- + +# Browser Screenshot + +截取当前页面截图。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| path | string | 否 | 保存路径(可选,不填自动生成) | + +## Examples + +**截取当前页面**: +```json +{} +``` + +**保存到指定路径**: +```json +{"path": "C:/screenshots/result.png"} +``` + +## Notes + +- 仅截取浏览器页面内容 +- 如需截取桌面或其他应用,请使用 `desktop_screenshot` + +## Workflow + +1. 截图后获取 `file_path` +2. 使用 `deliver_artifacts` 发送给用户 + +## Related Skills + +- `desktop-screenshot`: 截取桌面应用 +- `deliver-artifacts`: 发送截图给用户 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-status/.openakita-i18n.json b/account/admin/skills/system/browser-status/.openakita-i18n.json new file mode 100644 index 0000000..b22a5be --- /dev/null +++ b/account/admin/skills/system/browser-status/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "浏览器状态", + "description": "检查浏览器当前状态,包括打开状态、当前 URL、页面标题和标签数量。" + } +} diff --git a/account/admin/skills/system/browser-status/SKILL.md b/account/admin/skills/system/browser-status/SKILL.md new file mode 100644 index 0000000..9804c25 --- /dev/null +++ b/account/admin/skills/system/browser-status/SKILL.md @@ -0,0 +1,44 @@ +--- +name: browser-status +description: Check browser current state including open status, current URL, page title, tab count. Useful for checking current page URL/title. Note - browser_open already includes status check and auto-starts if needed, so you don't need to call browser_status before browser_open. +system: true +handler: browser +tool-name: browser_status +category: Browser +--- + +# Browser Status + +获取浏览器当前状态。 + +## Parameters + +无参数。 + +## Returns + +- `is_open`: 浏览器是否打开 +- `url`: 当前页面 URL +- `title`: 当前页面标题 +- `tab_count`: 打开的标签页数量 + +## Notes + +- 用于查看当前页面 URL、标题、标签页数量 +- `browser_open` 已包含状态检查,不需要先调 `browser_status` 再调 `browser_open` +- `browser_task` 和 `browser_navigate` 会自动启动浏览器,无需手动检查 + +## Related Skills + +- `browser-open`: 如果状态显示未运行则调用 +- `browser-navigate`: 状态检查后导航 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-switch-tab/.openakita-i18n.json b/account/admin/skills/system/browser-switch-tab/.openakita-i18n.json new file mode 100644 index 0000000..fb0d9a4 --- /dev/null +++ b/account/admin/skills/system/browser-switch-tab/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "切换标签页", + "description": "按索引切换到指定浏览器标签页,用于在不同页面间切换。" + } +} diff --git a/account/admin/skills/system/browser-switch-tab/SKILL.md b/account/admin/skills/system/browser-switch-tab/SKILL.md new file mode 100644 index 0000000..0244cdc --- /dev/null +++ b/account/admin/skills/system/browser-switch-tab/SKILL.md @@ -0,0 +1,38 @@ +--- +name: browser-switch-tab +description: Switch to a specific browser tab by index. When you need to work with a different tab or return to previous page. Use browser_list_tabs to get tab indices. +system: true +handler: browser +tool-name: browser_switch_tab +category: Browser +--- + +# Browser Switch Tab + +切换到指定的标签页。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| index | number | 是 | 标签页索引(从 0 开始) | + +## Workflow + +1. 先用 `browser_list_tabs` 获取所有标签页 +2. 使用返回的索引切换 + +## Related Skills + +- `browser-list-tabs`: 获取标签页列表 +- `browser-new-tab`: 新建标签页 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/browser-task/.openakita-i18n.json b/account/admin/skills/system/browser-task/.openakita-i18n.json new file mode 100644 index 0000000..6d99594 --- /dev/null +++ b/account/admin/skills/system/browser-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "浏览器任务", + "description": "智能浏览器任务——描述任务目标,自动完成操作(推荐优先使用)。" + } +} diff --git a/account/admin/skills/system/browser-task/SKILL.md b/account/admin/skills/system/browser-task/SKILL.md new file mode 100644 index 0000000..3ec669b --- /dev/null +++ b/account/admin/skills/system/browser-task/SKILL.md @@ -0,0 +1,122 @@ +--- +name: browser-task +description: 智能浏览器任务 - 描述任务,自动完成(推荐优先使用) +system: true +handler: browser +tool-name: browser_task +category: Browser +priority: high +--- + +# browser_task - 智能浏览器任务 + +**推荐优先使用** - 这是浏览器操作的首选工具。 + +基于 [browser-use](https://github.com/browser-use/browser-use) 开源项目实现。 + +## 用法 + +```python +browser_task( + task="要完成的任务描述", + max_steps=15 # 可选,默认 15 +) +``` + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| task | string | 是 | 任务描述,用自然语言描述你想完成的操作 | +| max_steps | integer | 否 | 最大执行步骤数,默认 15 | + +## 何时使用(优先) + +- 任何涉及多步骤的浏览器操作 +- 网页搜索、表单填写、信息提取 +- 不确定具体操作步骤时 +- 复杂的网页交互流程 + +## 示例 + +### 搜索任务 +```python +browser_task(task="打开百度搜索福建福州天气") +``` + +### 表单填写 +```python +browser_task(task="打开 example.com 的注册页面,填写用户名 test123") +``` + +### 信息提取 +```python +browser_task(task="打开 GitHub 首页,获取今日热门项目的名称") +``` + +### 截图任务 +```python +browser_task(task="打开百度搜索福建福州,截图保存") +``` + +## 何时使用细粒度工具 + +仅在以下情况使用 `browser_navigate`、`browser_click` 等细粒度工具: + +- `browser_task` 执行失败需要手动介入 +- 仅需单步操作(如只截图 `browser_screenshot`) +- 需要精确控制特定元素 + +## 返回值 + +```json +{ + "success": true, + "result": { + "task": "打开百度搜索福建福州", + "steps_taken": 5, + "final_result": "搜索完成,已显示福建福州相关结果", + "message": "任务完成: 打开百度搜索福建福州" + } +} +``` + +## 注意事项 + +1. 任务描述要清晰具体,避免歧义 +2. 复杂任务可能需要增加 max_steps +3. 首次使用会自动启动浏览器(可见模式) +4. **自动继承系统 LLM 配置**,无需额外配置 API Key + +## 技术细节 + +- 通过 CDP (Chrome DevTools Protocol) 复用 OpenAkita 已启动的浏览器 +- 自动继承 OpenAkita 系统配置的 LLM(来自 llm_endpoints.json) +- 基于 [browser-use](https://github.com/browser-use/browser-use) 开源项目 + +## 高级:操作用户已打开的 Chrome + +如果想让 OpenAkita 操作你已打开的 Chrome 页面,需要以调试模式启动 Chrome: + +**Windows:** +```cmd +"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 +``` + +**macOS:** +```bash +/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 +``` + +**Linux:** +```bash +google-chrome --remote-debugging-port=9222 +``` + +启动后,OpenAkita 会自动检测并连接,可以操作你已打开的标签页。 + +## 相关技能 + +- `browser_screenshot` - 单独截图 +- `browser_navigate` - 单独导航 +- `deliver_artifacts` - 发送结果给用户 diff --git a/account/admin/skills/system/browser-type/.openakita-i18n.json b/account/admin/skills/system/browser-type/.openakita-i18n.json new file mode 100644 index 0000000..ae53905 --- /dev/null +++ b/account/admin/skills/system/browser-type/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "网页输入", + "description": "在网页输入框中输入文本,用于填写表单、输入搜索词或录入数据。" + } +} diff --git a/account/admin/skills/system/browser-type/SKILL.md b/account/admin/skills/system/browser-type/SKILL.md new file mode 100644 index 0000000..ff2ae5c --- /dev/null +++ b/account/admin/skills/system/browser-type/SKILL.md @@ -0,0 +1,56 @@ +--- +name: browser-type +description: Type text into input fields on webpage. When you need to fill forms, enter search queries, or input data. PREREQUISITE - must use browser_navigate first. May need to click field first for focus. +system: true +handler: browser +tool-name: browser_type +category: Browser +--- + +# Browser Type + +在输入框中输入文本。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| selector | string | 是 | 输入框的 CSS 选择器 | +| text | string | 是 | 要输入的文本 | + +## Examples + +**在搜索框输入**: +```json +{"selector": "input[name='q']", "text": "OpenAkita"} +``` + +**填写用户名**: +```json +{"selector": "#username", "text": "admin"} +``` + +## Prerequisites + +- 必须先用 `browser_navigate` 打开目标页面 +- 如果输入框没有焦点,可能需要先点击 + +## Notes + +- 支持中文输入 +- 输入会追加到现有内容(如需清空请先选中) + +## Related Skills + +- `browser-navigate`: 先导航到页面 +- `browser-click`: 点击输入框获取焦点 + + +## 推荐 + +对于多步骤的浏览器任务,建议优先使用 `browser_task` 工具。它可以自动规划和执行复杂的浏览器操作,无需手动逐步调用各个工具。 + +示例: +```python +browser_task(task="打开百度搜索福建福州并截图") +``` diff --git a/account/admin/skills/system/call-mcp-tool/.openakita-i18n.json b/account/admin/skills/system/call-mcp-tool/.openakita-i18n.json new file mode 100644 index 0000000..242a852 --- /dev/null +++ b/account/admin/skills/system/call-mcp-tool/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "调用 MCP 工具", + "description": "调用 MCP 服务器工具以获取扩展功能,需查看系统提示中的可用服务器和工具列表。" + } +} diff --git a/account/admin/skills/system/call-mcp-tool/SKILL.md b/account/admin/skills/system/call-mcp-tool/SKILL.md new file mode 100644 index 0000000..64953e9 --- /dev/null +++ b/account/admin/skills/system/call-mcp-tool/SKILL.md @@ -0,0 +1,39 @@ +--- +name: call-mcp-tool +description: Call MCP server tool for extended capabilities. Check 'MCP Servers' section in system prompt for available servers and tools. When you need to use external service or access specialized functionality. +system: true +handler: mcp +tool-name: call_mcp_tool +category: MCP +--- + +# Call MCP Tool + +调用 MCP 服务器的工具。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| server | string | 是 | MCP 服务器标识符 | +| tool_name | string | 是 | 工具名称 | +| arguments | object | 否 | 工具参数,默认 {} | + +## Usage + +查看系统提示中的 'MCP Servers' 部分了解可用的服务器和工具。 + +## Examples + +```json +{ + "server": "my-server", + "tool_name": "search", + "arguments": {"query": "example"} +} +``` + +## Related Skills + +- `list-mcp-servers`: 列出可用服务器 +- `get-mcp-instructions`: 获取使用说明 diff --git a/account/admin/skills/system/cancel-scheduled-task/.openakita-i18n.json b/account/admin/skills/system/cancel-scheduled-task/.openakita-i18n.json new file mode 100644 index 0000000..80fb42f --- /dev/null +++ b/account/admin/skills/system/cancel-scheduled-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "取消定时任务", + "description": "永久删除指定的定时任务。" + } +} diff --git a/account/admin/skills/system/cancel-scheduled-task/SKILL.md b/account/admin/skills/system/cancel-scheduled-task/SKILL.md new file mode 100644 index 0000000..7c73269 --- /dev/null +++ b/account/admin/skills/system/cancel-scheduled-task/SKILL.md @@ -0,0 +1,32 @@ +--- +name: cancel-scheduled-task +description: PERMANENTLY DELETE scheduled task. When user says 'cancel/delete task' use this. When user says 'turn off notification' use update_scheduled_task with notify=false. When user says 'pause task' use update_scheduled_task with enabled=false. +system: true +handler: scheduled +tool-name: cancel_scheduled_task +category: Scheduled Tasks +--- + +# Cancel Scheduled Task + +【永久删除】定时任务。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| task_id | string | 是 | 任务 ID | + +## Important + +**操作区分**: +- 用户说"取消/删除任务" → 用此工具 +- 用户说"关闭提醒" → 用 `update_scheduled_task` 设 notify=false +- 用户说"暂停任务" → 用 `update_scheduled_task` 设 enabled=false + +**注意**:删除后无法恢复! + +## Related Skills + +- `list-scheduled-tasks`: 获取任务 ID +- `update-scheduled-task`: 修改任务设置 diff --git a/account/admin/skills/system/complete-plan/.openakita-i18n.json b/account/admin/skills/system/complete-plan/.openakita-i18n.json new file mode 100644 index 0000000..9d527dc --- /dev/null +++ b/account/admin/skills/system/complete-plan/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "完成计划", + "description": "标记计划为已完成并生成执行总结报告,在所有步骤完成后调用。" + } +} diff --git a/account/admin/skills/system/complete-plan/SKILL.md b/account/admin/skills/system/complete-plan/SKILL.md new file mode 100644 index 0000000..740c17f --- /dev/null +++ b/account/admin/skills/system/complete-plan/SKILL.md @@ -0,0 +1,38 @@ +--- +name: complete-plan +description: Mark the plan as completed and generate a summary report. Call when ALL steps are done. Returns execution summary with success/failure statistics. +system: true +handler: plan +tool-name: complete_plan +category: Plan +--- + +# Complete Plan + +标记计划完成,生成最终报告。在所有步骤完成后调用。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| summary | string | 是 | 完成总结 | + +## Examples + +```json +{ + "summary": "已完成百度搜索天气并截图发送给用户" +} +``` + +## Returns + +- 执行摘要 +- 成功/失败统计 +- 总耗时 + +## Related Skills + +- `create-plan`: 创建计划 +- `update-plan-step`: 更新步骤状态 +- `get-plan-status`: 查看计划状态 diff --git a/account/admin/skills/system/create-plan/.openakita-i18n.json b/account/admin/skills/system/create-plan/.openakita-i18n.json new file mode 100644 index 0000000..344f05b --- /dev/null +++ b/account/admin/skills/system/create-plan/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "创建计划", + "description": "为多步骤任务创建执行计划,在需要 2 个以上工具调用时必须首先创建计划。" + } +} diff --git a/account/admin/skills/system/create-plan/SKILL.md b/account/admin/skills/system/create-plan/SKILL.md new file mode 100644 index 0000000..3f9d7a3 --- /dev/null +++ b/account/admin/skills/system/create-plan/SKILL.md @@ -0,0 +1,60 @@ +--- +name: create-plan +description: "MUST CALL FIRST for multi-step tasks! If user request needs 2+ tool calls (like 'open + search + screenshot'), call create_plan BEFORE any other tool." +system: true +handler: plan +tool-name: create_plan +category: Plan +--- + +# Create Plan + +创建任务执行计划。多步骤任务必须先创建计划再执行。 + +## When to Use + +- 任务需要超过 2 步完成时 +- 用户请求中有"然后"、"接着"、"之后"等词 +- 涉及多个工具协作 + +## Workflow + +1. `create-plan` → 2. 执行步骤 → 3. `update-plan-step` → 4. ... → 5. `complete-plan` + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| task_summary | string | 是 | 任务的一句话总结 | +| steps | array | 是 | 步骤列表 | + +### Step Item + +| 字段 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| id | string | 是 | 步骤 ID(如 step_1) | +| description | string | 是 | 步骤描述 | +| tool | string | 否 | 预计使用的工具 | +| skills | array | 否 | 关联的 skill 名称列表(可选,用于追踪) | +| depends_on | array | 否 | 依赖的步骤 ID | + +## Examples + +**打开百度搜索天气并截图发给用户**: +```json +{ + "task_summary": "打开百度搜索天气并截图发送", + "steps": [ + {"id": "step_1", "description": "打开百度", "tool": "browser_navigate", "skills": ["browser-navigate"]}, + {"id": "step_2", "description": "输入搜索关键词", "tool": "browser_type", "skills": ["browser-type"], "depends_on": ["step_1"]}, + {"id": "step_3", "description": "截图", "tool": "browser_screenshot", "skills": ["browser-screenshot"], "depends_on": ["step_2"]}, + {"id": "step_4", "description": "发送截图", "tool": "deliver_artifacts", "skills": ["deliver-artifacts"], "depends_on": ["step_3"]} + ] +} +``` + +## Related Skills + +- `update-plan-step`: 更新步骤状态 +- `get-plan-status`: 查看计划状态 +- `complete-plan`: 完成计划 diff --git a/account/admin/skills/system/deliver-artifacts/.openakita-i18n.json b/account/admin/skills/system/deliver-artifacts/.openakita-i18n.json new file mode 100644 index 0000000..82b3cdb --- /dev/null +++ b/account/admin/skills/system/deliver-artifacts/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "发送文件", + "description": "通过 IM 网关发送文件、图片或语音到当前聊天会话,返回发送回执。" + } +} diff --git a/account/admin/skills/system/deliver-artifacts/SKILL.md b/account/admin/skills/system/deliver-artifacts/SKILL.md new file mode 100644 index 0000000..9bdc7ef --- /dev/null +++ b/account/admin/skills/system/deliver-artifacts/SKILL.md @@ -0,0 +1,54 @@ +--- +name: deliver-artifacts +description: Deliver artifacts (files/images/voice) to current IM chat via gateway, returning a receipt. Use this as the only delivery proof for attachments. Text replies are sent automatically - only use this for file/image/voice attachments. +system: true +handler: im_channel +tool-name: deliver_artifacts +category: IM Channel +--- + +# Deliver Artifacts + +通过网关向当前 IM 聊天交付附件(文件/图片/语音),并返回结构化回执。 + +## Important + +- **文本回复**由网关直接转发,不需要用工具发送 +- **附件交付**必须使用本工具,回执是"已交付"的唯一证据 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| artifacts | array | 是 | 要交付的附件清单 | +| mode | string | 否 | send 或 preview(默认 send) | + +### Artifact Item + +| 字段 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| type | string | 是 | file / image / voice | +| path | string | 是 | 本地文件路径 | +| caption | string | 否 | 说明文字 | + +## Examples + +**发送截图**: +```json +{ + "artifacts": [{"type": "image", "path": "data/temp/screenshot.png", "caption": "页面截图"}] +} +``` + +**发送文件**: +```json +{ + "artifacts": [{"type": "file", "path": "data/out/report.md"}] +} +``` + +## Related Skills + +- `browser-screenshot`: 网页截图 +- `desktop-screenshot`: 桌面截图 +- `get-voice-file`: 获取语音文件 diff --git a/account/admin/skills/system/desktop-click/.openakita-i18n.json b/account/admin/skills/system/desktop-click/.openakita-i18n.json new file mode 100644 index 0000000..aab9a82 --- /dev/null +++ b/account/admin/skills/system/desktop-click/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "桌面点击", + "description": "点击桌面元素或坐标,用于点击按钮/图标、选择菜单项或与桌面 UI 交互。" + } +} diff --git a/account/admin/skills/system/desktop-click/SKILL.md b/account/admin/skills/system/desktop-click/SKILL.md new file mode 100644 index 0000000..bacb20a --- /dev/null +++ b/account/admin/skills/system/desktop-click/SKILL.md @@ -0,0 +1,65 @@ +--- +name: desktop-click +description: Click desktop elements or coordinates. When you need to click buttons/icons in applications, select menu items, or interact with desktop UI. Supports element description, name prefix, or coordinates. For browser webpage elements, use browser_click instead. +system: true +handler: desktop +tool-name: desktop_click +category: Desktop +--- + +# Desktop Click + +点击桌面上的 UI 元素或指定坐标。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| target | string | 是 | 元素描述或坐标(如 '确定按钮' 或 '100,200') | +| button | string | 否 | 鼠标按钮:left, right, middle,默认 left | +| double | boolean | 否 | 是否双击,默认 false | +| method | string | 否 | 查找方法:auto, uia, vision,默认 auto | + +## Target Formats + +- 元素描述:`"保存按钮"`、`"name:确定"` +- 坐标:`"100,200"` + +## Find Methods + +- `auto`: 自动选择(推荐) +- `uia`: 只用 UIAutomation +- `vision`: 只用视觉识别 + +## Examples + +**点击按钮(元素描述)**: +```json +{"target": "确定按钮"} +``` + +**点击坐标**: +```json +{"target": "100,200"} +``` + +**右键点击**: +```json +{"target": "文件图标", "button": "right"} +``` + +**双击打开**: +```json +{"target": "文档.txt", "double": true} +``` + +## Notes + +- 如果点击的是浏览器内的网页元素,请使用 `browser_click` +- 优先使用 UIAutomation(快速准确),失败时用视觉识别 + +## Related Skills + +- `browser-click`: 点击浏览器网页元素 +- `desktop-type`: 输入文本 +- `desktop-find-element`: 先查找元素 diff --git a/account/admin/skills/system/desktop-find-element/.openakita-i18n.json b/account/admin/skills/system/desktop-find-element/.openakita-i18n.json new file mode 100644 index 0000000..490b1ca --- /dev/null +++ b/account/admin/skills/system/desktop-find-element/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "查找桌面元素", + "description": "使用 UI 自动化或视觉识别查找桌面 UI 元素,定位按钮、菜单和图标。" + } +} diff --git a/account/admin/skills/system/desktop-find-element/SKILL.md b/account/admin/skills/system/desktop-find-element/SKILL.md new file mode 100644 index 0000000..d11f42c --- /dev/null +++ b/account/admin/skills/system/desktop-find-element/SKILL.md @@ -0,0 +1,48 @@ +--- +name: desktop-find-element +description: Find desktop UI elements using UIAutomation (fast, accurate) or vision recognition (fallback). When you need to locate buttons/menus/icons, get element positions before clicking, or verify UI state. For browser webpage elements, use browser_* tools instead. +system: true +handler: desktop +tool-name: desktop_find_element +category: Desktop +--- + +# Desktop Find Element + +查找桌面 UI 元素。优先使用 UIAutomation(快速准确),失败时用视觉识别(通用)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| target | string | 是 | 元素描述,如 '保存按钮'、'name:文件'、'id:btn_ok' | +| window_title | string | 否 | 限定在某个窗口内查找 | +| method | string | 否 | 查找方法:auto(默认)、uia、vision | + +## Supported Target Formats + +- 自然语言:"保存按钮"、"红色图标" +- 按名称:"name:保存" +- 按 ID:"id:btn_save" +- 按类型:"type:Button" + +## Find Methods + +- `auto`: 自动选择(推荐) +- `uia`: 只用 UIAutomation +- `vision`: 只用视觉识别 + +## Returns + +- 元素位置(x, y) +- 元素大小 +- 元素属性 + +## Warning + +如果操作的是浏览器内的网页元素,请使用 `browser_*` 工具。 + +## Related Skills + +- `desktop-click`: 点击找到的元素 +- `desktop-inspect`: 查看元素树结构 diff --git a/account/admin/skills/system/desktop-hotkey/.openakita-i18n.json b/account/admin/skills/system/desktop-hotkey/.openakita-i18n.json new file mode 100644 index 0000000..73cb8db --- /dev/null +++ b/account/admin/skills/system/desktop-hotkey/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "键盘快捷键", + "description": "执行键盘快捷键,如复制粘贴、保存文件、关闭窗口、撤销重做等。" + } +} diff --git a/account/admin/skills/system/desktop-hotkey/SKILL.md b/account/admin/skills/system/desktop-hotkey/SKILL.md new file mode 100644 index 0000000..dbd8e90 --- /dev/null +++ b/account/admin/skills/system/desktop-hotkey/SKILL.md @@ -0,0 +1,50 @@ +--- +name: desktop-hotkey +description: Execute keyboard shortcuts. When you need to copy/paste (Ctrl+C/V), save files (Ctrl+S), close windows (Alt+F4), undo/redo (Ctrl+Z/Y), or select all (Ctrl+A). +system: true +handler: desktop +tool-name: desktop_hotkey +category: Desktop +--- + +# Desktop Hotkey + +执行键盘快捷键。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| keys | array | 是 | 按键组合数组,如 ['ctrl', 'c'] | + +## Common Shortcuts + +| 快捷键 | 功能 | +|--------|------| +| ['ctrl', 'c'] | 复制 | +| ['ctrl', 'v'] | 粘贴 | +| ['ctrl', 'x'] | 剪切 | +| ['ctrl', 's'] | 保存 | +| ['ctrl', 'z'] | 撤销 | +| ['ctrl', 'y'] | 重做 | +| ['ctrl', 'a'] | 全选 | +| ['alt', 'f4'] | 关闭窗口 | +| ['alt', 'tab'] | 切换窗口 | +| ['win', 'd'] | 显示桌面 | + +## Examples + +**复制选中内容**: +```json +{"keys": ["ctrl", "c"]} +``` + +**保存文件**: +```json +{"keys": ["ctrl", "s"]} +``` + +## Related Skills + +- `desktop-type`: 输入文本 +- `desktop-click`: 点击元素 diff --git a/account/admin/skills/system/desktop-inspect/.openakita-i18n.json b/account/admin/skills/system/desktop-inspect/.openakita-i18n.json new file mode 100644 index 0000000..d8d1689 --- /dev/null +++ b/account/admin/skills/system/desktop-inspect/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "桌面 UI 检查", + "description": "检查窗口 UI 元素树结构,用于调试 UI 自动化问题和理解界面布局。" + } +} diff --git a/account/admin/skills/system/desktop-inspect/SKILL.md b/account/admin/skills/system/desktop-inspect/SKILL.md new file mode 100644 index 0000000..78d73c7 --- /dev/null +++ b/account/admin/skills/system/desktop-inspect/SKILL.md @@ -0,0 +1,50 @@ +--- +name: desktop-inspect +description: Inspect window UI element tree structure for debugging and understanding interface layout. When you need to debug UI automation issues, understand application structure, or find correct element identifiers. +system: true +handler: desktop +tool-name: desktop_inspect +category: Desktop +--- + +# Desktop Inspect + +检查窗口的 UI 元素树结构(用于调试和了解界面结构)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| window_title | string | 否 | 窗口标题,不填则检查当前活动窗口 | +| depth | integer | 否 | 元素树遍历深度,默认 2 | + +## Use Cases + +- 调试 UI 自动化问题 +- 了解应用程序界面结构 +- 查找正确的元素标识符用于点击/输入 + +## Examples + +**检查当前窗口**: +```json +{} +``` + +**检查记事本,深度 3**: +```json +{"window_title": "记事本", "depth": 3} +``` + +## Returns + +- 元素名称 +- 元素类型 +- 元素 ID +- 元素位置 +- 子元素列表 + +## Related Skills + +- `desktop-find-element`: 查找特定元素 +- `desktop-window`: 窗口管理 diff --git a/account/admin/skills/system/desktop-screenshot/.openakita-i18n.json b/account/admin/skills/system/desktop-screenshot/.openakita-i18n.json new file mode 100644 index 0000000..52963bb --- /dev/null +++ b/account/admin/skills/system/desktop-screenshot/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "桌面截图", + "description": "捕获 Windows 桌面截图并自动保存文件,用于记录桌面状态和操作结果。" + } +} diff --git a/account/admin/skills/system/desktop-screenshot/SKILL.md b/account/admin/skills/system/desktop-screenshot/SKILL.md new file mode 100644 index 0000000..a1f82ca --- /dev/null +++ b/account/admin/skills/system/desktop-screenshot/SKILL.md @@ -0,0 +1,62 @@ +--- +name: desktop-screenshot +description: Capture Windows desktop screenshot with automatic file saving. When you need to show desktop state, capture application windows, or record operation results. IMPORTANT - must actually call this tool, never say 'screenshot done' without calling. Returns file_path for deliver_artifacts. +system: true +handler: desktop +tool-name: desktop_screenshot +category: Desktop +--- + +# Desktop Screenshot + +截取 Windows 桌面屏幕截图。 + +## Important + +**用户要求截图时,必须实际调用此工具。禁止不调用就说"截图完成"!** + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| path | string | 否 | 保存路径(可选,自动生成) | +| window_title | string | 否 | 只截取指定窗口(模糊匹配) | +| analyze | boolean | 否 | 是否用视觉模型分析,默认 false | +| analyze_query | string | 否 | 分析查询(需要 analyze=true) | + +## Examples + +**截取整个桌面**: +```json +{} +``` + +**截取指定窗口**: +```json +{"window_title": "记事本"} +``` + +**截取并分析**: +```json +{ + "analyze": true, + "analyze_query": "找到所有按钮" +} +``` + +## Workflow + +1. 调用此工具截图 +2. 获取返回的 `file_path` +3. 用 `deliver_artifacts` 发送给用户 + +## Notes + +- 如果只涉及浏览器内的网页操作,请使用 `browser_screenshot` +- 截图默认保存到用户桌面 + +## Related Skills + +- `browser-screenshot`: 截取浏览器页面 +- `deliver-artifacts`: 发送截图给用户 +- `desktop-click`: 点击桌面元素 diff --git a/account/admin/skills/system/desktop-scroll/.openakita-i18n.json b/account/admin/skills/system/desktop-scroll/.openakita-i18n.json new file mode 100644 index 0000000..92f6eb2 --- /dev/null +++ b/account/admin/skills/system/desktop-scroll/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "桌面滚动", + "description": "滚动鼠标滚轮,用于翻页、浏览长列表或配合 Ctrl 键缩放。" + } +} diff --git a/account/admin/skills/system/desktop-scroll/SKILL.md b/account/admin/skills/system/desktop-scroll/SKILL.md new file mode 100644 index 0000000..6b6b1e7 --- /dev/null +++ b/account/admin/skills/system/desktop-scroll/SKILL.md @@ -0,0 +1,49 @@ +--- +name: desktop-scroll +description: Scroll mouse wheel in specified direction. When you need to scroll page/document content, navigate long lists, or zoom in/out with Ctrl. Directions - up/down/left/right. +system: true +handler: desktop +tool-name: desktop_scroll +category: Desktop +--- + +# Desktop Scroll + +滚动鼠标滚轮。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| direction | string | 是 | 滚动方向:up/down/left/right | +| amount | integer | 否 | 滚动格数,默认 3 | + +## Directions + +- `up`: 向上滚动 +- `down`: 向下滚动 +- `left`: 向左滚动 +- `right`: 向右滚动 + +## Examples + +**向下滚动**: +```json +{"direction": "down"} +``` + +**向上滚动 5 格**: +```json +{"direction": "up", "amount": 5} +``` + +## Use Cases + +- 滚动页面/文档内容 +- 浏览长列表 +- 配合 Ctrl 键缩放 + +## Related Skills + +- `desktop-click`: 点击滚动区域 +- `desktop-hotkey`: 快捷键操作 diff --git a/account/admin/skills/system/desktop-type/.openakita-i18n.json b/account/admin/skills/system/desktop-type/.openakita-i18n.json new file mode 100644 index 0000000..65900ce --- /dev/null +++ b/account/admin/skills/system/desktop-type/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "桌面输入", + "description": "在桌面应用当前光标位置输入文本,用于填写对话框、输入框或文本编辑器。" + } +} diff --git a/account/admin/skills/system/desktop-type/SKILL.md b/account/admin/skills/system/desktop-type/SKILL.md new file mode 100644 index 0000000..4e3ff1e --- /dev/null +++ b/account/admin/skills/system/desktop-type/SKILL.md @@ -0,0 +1,50 @@ +--- +name: desktop-type +description: Type text at current cursor position in desktop applications. When you need to enter text in dialogs, fill input fields, or type in text editors. Supports Chinese input. For browser webpage forms, use browser_type instead. +system: true +handler: desktop +tool-name: desktop_type +category: Desktop +--- + +# Desktop Type + +在当前焦点位置输入文本。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| text | string | 是 | 要输入的文本 | +| clear_first | boolean | 否 | 是否先清空现有内容(Ctrl+A 后输入),默认 false | + +## Features + +- 支持中文输入 +- 支持先清空再输入 + +## Workflow + +1. 先用 `desktop-click` 点击目标输入框获得焦点 +2. 调用此工具输入文本 + +## Examples + +**直接输入**: +```json +{"text": "Hello World"} +``` + +**清空后输入**: +```json +{"text": "New content", "clear_first": true} +``` + +## Warning + +如果输入的是浏览器内的网页表单,请使用 `browser_type` 工具。 + +## Related Skills + +- `desktop-click`: 先点击获取焦点 +- `desktop-hotkey`: 快捷键操作 diff --git a/account/admin/skills/system/desktop-wait/.openakita-i18n.json b/account/admin/skills/system/desktop-wait/.openakita-i18n.json new file mode 100644 index 0000000..c301f13 --- /dev/null +++ b/account/admin/skills/system/desktop-wait/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "等待元素", + "description": "等待 UI 元素或窗口出现,用于等待对话框打开、加载完成或同步应用状态。" + } +} diff --git a/account/admin/skills/system/desktop-wait/SKILL.md b/account/admin/skills/system/desktop-wait/SKILL.md new file mode 100644 index 0000000..59b89da --- /dev/null +++ b/account/admin/skills/system/desktop-wait/SKILL.md @@ -0,0 +1,53 @@ +--- +name: desktop-wait +description: Wait for UI element or window to appear. When you need to wait for dialog to open, loading to complete, or synchronize with application state before next action. Default timeout is 10 seconds. +system: true +handler: desktop +tool-name: desktop_wait +category: Desktop +--- + +# Desktop Wait + +等待某个 UI 元素或窗口出现。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| target | string | 是 | 元素描述或窗口标题 | +| target_type | string | 否 | 目标类型:element(默认)/ window | +| timeout | integer | 否 | 超时时间(秒),默认 10 | + +## Target Types + +- `element`: 等待 UI 元素出现 +- `window`: 等待窗口出现 + +## Use Cases + +- 等待对话框打开 +- 等待加载完成 +- 在下一步操作前同步应用状态 + +## Examples + +**等待保存对话框**: +```json +{"target": "另存为", "target_type": "window"} +``` + +**等待确定按钮**: +```json +{"target": "确定按钮", "timeout": 5} +``` + +## Returns + +- 成功:元素/窗口信息 +- 超时:错误信息 + +## Related Skills + +- `desktop-click`: 等待后点击 +- `desktop-find-element`: 查找元素 diff --git a/account/admin/skills/system/desktop-window/.openakita-i18n.json b/account/admin/skills/system/desktop-window/.openakita-i18n.json new file mode 100644 index 0000000..8e06519 --- /dev/null +++ b/account/admin/skills/system/desktop-window/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "窗口管理", + "description": "管理桌面窗口操作:列出窗口、切换窗口、最小化/最大化/还原和关闭窗口。" + } +} diff --git a/account/admin/skills/system/desktop-window/SKILL.md b/account/admin/skills/system/desktop-window/SKILL.md new file mode 100644 index 0000000..165ab9b --- /dev/null +++ b/account/admin/skills/system/desktop-window/SKILL.md @@ -0,0 +1,58 @@ +--- +name: desktop-window +description: Window management operations. When you need to list all open windows, switch to a specific window, minimize/maximize/restore windows, or close windows. Use title parameter for targeting specific window (fuzzy match). +system: true +handler: desktop +tool-name: desktop_window +category: Desktop +--- + +# Desktop Window + +窗口管理操作。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| action | string | 是 | 操作类型:list/switch/minimize/maximize/restore/close | +| title | string | 否 | 窗口标题(模糊匹配),list 操作不需要 | + +## Actions + +| 操作 | 说明 | 需要 title | +|------|------|-----------| +| list | 列出所有窗口 | 否 | +| switch | 切换到指定窗口(激活并置顶) | 是 | +| minimize | 最小化窗口 | 是 | +| maximize | 最大化窗口 | 是 | +| restore | 恢复窗口 | 是 | +| close | 关闭窗口 | 是 | + +## Examples + +**列出所有窗口**: +```json +{"action": "list"} +``` + +**切换到记事本**: +```json +{"action": "switch", "title": "记事本"} +``` + +**最大化 Chrome**: +```json +{"action": "maximize", "title": "Chrome"} +``` + +## Returns (list action) + +- 窗口标题 +- 窗口句柄 +- 窗口位置和大小 + +## Related Skills + +- `desktop-screenshot`: 截取窗口 +- `desktop-inspect`: 检查窗口结构 diff --git a/account/admin/skills/system/enable-thinking/.openakita-i18n.json b/account/admin/skills/system/enable-thinking/.openakita-i18n.json new file mode 100644 index 0000000..8fcecfe --- /dev/null +++ b/account/admin/skills/system/enable-thinking/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "深度思考开关", + "description": "控制深度思考模式的开启和关闭,对简单任务可临时关闭以加速响应。" + } +} diff --git a/account/admin/skills/system/enable-thinking/SKILL.md b/account/admin/skills/system/enable-thinking/SKILL.md new file mode 100644 index 0000000..e5e0e25 --- /dev/null +++ b/account/admin/skills/system/enable-thinking/SKILL.md @@ -0,0 +1,26 @@ +--- +name: enable-thinking +description: Control deep thinking mode. Default enabled. For very simple tasks (simple reminders, greetings, quick queries), can temporarily disable to speed up response. Auto-restores to enabled after completion. +system: true +handler: system +tool-name: enable_thinking +category: System +--- + +# Enable Thinking + +控制深度思考模式。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| enabled | boolean | 是 | 是否启用 thinking 模式 | +| reason | string | 是 | 简要说明原因 | + +## Notes + +- 默认状态:启用 +- 可临时关闭的场景:简单提醒、简单问候、快速查询 +- 完成后会自动恢复默认启用状态 +- 复杂任务建议保持启用 diff --git a/account/admin/skills/system/export-agent/SKILL.md b/account/admin/skills/system/export-agent/SKILL.md new file mode 100644 index 0000000..622768a --- /dev/null +++ b/account/admin/skills/system/export-agent/SKILL.md @@ -0,0 +1,34 @@ +--- +name: export-agent +description: Export a local Agent profile as a portable .akita-agent package file. Use when user wants to share, backup, or distribute an Agent with its skills and configuration. +system: true +handler: agent_package +tool-name: export_agent +category: Agent Package +--- + +# Export Agent + +将本地 Agent 导出为 `.akita-agent` 包文件,包含 Agent 配置、提示词和捆绑技能。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| profile_id | string | 是 | 要导出的 Agent Profile ID | +| author_name | string | 否 | 作者名称 | +| version | string | 否 | 版本号(默认 1.0.0) | +| include_skills | array | 否 | 要打包的技能列表(默认为 Agent 配置中的本地技能) | + +## Usage + +导出后的 `.akita-agent` 文件可以: +- 发送给其他用户导入使用 +- 上传到 Agent Store 分享 +- 作为 Agent 备份 + +## Related Skills + +- `import-agent`: 导入 Agent 包 +- `list-exportable-agents`: 列出可导出的 Agent +- `inspect-agent-package`: 预览包内容 diff --git a/account/admin/skills/system/find-skills/.openakita-i18n.json b/account/admin/skills/system/find-skills/.openakita-i18n.json new file mode 100644 index 0000000..376a9a5 --- /dev/null +++ b/account/admin/skills/system/find-skills/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "发现技能", + "description": "帮助用户发现和安装适合的技能,当用户问「怎么做某事」或「有没有某个功能」时使用。" + } +} diff --git a/account/admin/skills/system/find-skills/SKILL.md b/account/admin/skills/system/find-skills/SKILL.md new file mode 100644 index 0000000..98d10c3 --- /dev/null +++ b/account/admin/skills/system/find-skills/SKILL.md @@ -0,0 +1,133 @@ +--- +name: find-skills +description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill. +system: true +handler: skills +tool-name: find_skills +category: Skills Management +--- + +# Find Skills + +This skill helps you discover and install skills from the open agent skills ecosystem. + +## When to Use This Skill + +Use this skill when the user: + +- Asks "how do I do X" where X might be a common task with an existing skill +- Says "find a skill for X" or "is there a skill for X" +- Asks "can you do X" where X is a specialized capability +- Expresses interest in extending agent capabilities +- Wants to search for tools, templates, or workflows +- Mentions they wish they had help with a specific domain (design, testing, deployment, etc.) + +## What is the Skills CLI? + +The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools. + +**Key commands:** + +- `npx skills find [query]` - Search for skills interactively or by keyword +- `npx skills add <source>` - Install a skill from GitHub or other sources +- `npx skills check` - Check for skill updates +- `npx skills update` - Update all installed skills + +**Browse skills at:** https://skills.sh/ + +## How to Help Users Find Skills + +### Step 1: Understand What They Need + +When a user asks for help with something, identify: + +1. The domain (e.g., React, testing, design, deployment) +2. The specific task (e.g., writing tests, creating animations, reviewing PRs) +3. Whether this is a common enough task that a skill likely exists + +### Step 2: Search for Skills + +Run the find command with a relevant query: + +```bash +npx skills find [query] +``` + +For example: + +- User asks "how do I make my React app faster?" → `npx skills find react performance` +- User asks "can you help me with PR reviews?" → `npx skills find pr review` +- User asks "I need to create a changelog" → `npx skills find changelog` + +The command will return results like: + +``` +Install with npx skills add <source> + +vercel-labs/agent-skills@vercel-react-best-practices +└ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices +``` + +### Step 3: Present Options to the User + +When you find relevant skills, present them to the user with: + +1. The skill name and what it does +2. The install command they can run +3. A link to learn more at skills.sh + +Example response: + +``` +I found a skill that might help! The "vercel-react-best-practices" skill provides +React and Next.js performance optimization guidelines from Vercel Engineering. + +To install it: +npx skills add vercel-labs/agent-skills@vercel-react-best-practices + +Learn more: https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices +``` + +### Step 4: Offer to Install + +If the user wants to proceed, you can install the skill for them: + +```bash +npx skills add -g -y <source> +``` + +The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts. + +## Common Skill Categories + +When searching, consider these common categories: + +| Category | Example Queries | +| --------------- | ---------------------------------------- | +| Web Development | react, nextjs, typescript, css, tailwind | +| Testing | testing, jest, playwright, e2e | +| DevOps | deploy, docker, kubernetes, ci-cd | +| Documentation | docs, readme, changelog, api-docs | +| Code Quality | review, lint, refactor, best-practices | +| Design | ui, ux, design-system, accessibility | +| Productivity | workflow, automation, git | + +## Tips for Effective Searches + +1. **Use specific keywords**: "react testing" is better than just "testing" +2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd" +3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills` + +## When No Skills Are Found + +If no relevant skills exist: + +1. Acknowledge that no existing skill was found +2. Offer to help with the task directly using your general capabilities +3. Suggest the user could create their own skill with `npx skills init` + +## Related Skills + +- `list-skills`: 查看已安装技能 +- `install-skill`: 安装新技能 +- `get-skill-info`: 获取技能详情 diff --git a/account/admin/skills/system/generate-agents-md/SKILL.md b/account/admin/skills/system/generate-agents-md/SKILL.md new file mode 100644 index 0000000..c4e6325 --- /dev/null +++ b/account/admin/skills/system/generate-agents-md/SKILL.md @@ -0,0 +1,108 @@ +--- +name: generate-agents-md +description: "Generate or update AGENTS.md for the current project. Use when user asks to create project guidelines, initialize AGENTS.md, standardize project conventions, or says '生成 AGENTS.md', '初始化项目规范'." +system: true +category: Development +allowed-tools: ["read_file", "write_file", "run_shell", "list_directory"] +--- + +# Generate AGENTS.md — 项目开发规范生成器 + +> **AGENTS.md** 是 AI 编码 Agent 的行业标准项目指引文件([agents.md](https://agents.md/)), +> 被 Cursor、Codex、Copilot、Jules、Windsurf、Aider、opencode 等 20+ 工具支持。 +> 一份文件,所有 AI 工具通用。 + +## When to Use + +- 用户说"生成 AGENTS.md"、"初始化项目规范"、"创建项目指引" +- 用户开始用 OpenAkita 开发一个新项目,还没有 AGENTS.md +- 用户说"帮我规范这个项目"、"让 AI 更好地理解这个项目" + +## Workflow + +### Step 1: 扫描项目结构 + +使用 `list_directory` 和 `read_file` 收集以下信息: + +1. **项目根文件**:检查 `package.json`、`pyproject.toml`、`Cargo.toml`、`go.mod`、`pom.xml`、`Gemfile`、`composer.json` 等,识别语言和框架 +2. **README.md**:读取项目描述和现有文档 +3. **配置文件**:`.eslintrc*`、`ruff.toml`、`pyproject.toml [tool.ruff]`、`.prettierrc`、`tsconfig.json` 等代码风格配置 +4. **CI/CD**:`.github/workflows/`、`.gitlab-ci.yml`、`Jenkinsfile` 等 +5. **测试**:`tests/`、`__tests__/`、`spec/`、`test/` 目录;`jest.config.*`、`vitest.config.*`、`pytest.ini`、`conftest.py` 等 +6. **目录结构**:顶层目录布局,识别 monorepo(`apps/`、`packages/`、`workspaces`) +7. **现有 AGENTS.md**:如果已存在,读取后在其基础上更新 + +### Step 2: 生成 AGENTS.md + +按以下模板结构生成,**只写与项目相关的段落**,省略不适用的部分: + +```markdown +# [Project Name] + +[一句话描述项目做什么] + +## Tech Stack + +- Language: [语言及版本] +- Framework: [框架] +- Package Manager: [包管理器] + +## Dev Environment Setup + +[环境准备步骤,如 Python 版本、Node 版本、依赖安装命令] + +## Build & Run + +[构建、启动、热重载等命令] + +## Testing + +[测试框架、运行命令、覆盖率要求] + +## Code Style + +[lint 工具、格式化工具、关键规则] + +## Project Structure + +[关键目录说明,不要列出每个文件] + +## Architecture Notes + +[核心架构设计、数据流、重要模块关系] + +## PR & Commit Conventions + +[提交信息格式、分支策略] + +## Known Gotchas + +[新手容易踩的坑、特殊约定] +``` + +### Step 3: 写入文件 + +使用 `write_file` 写入到项目根目录的 `AGENTS.md`。 + +### Step 4: Monorepo 检查 + +如果检测到 monorepo 结构(`apps/`、`packages/`、`services/` 等子项目),**询问用户**是否需要为子项目也生成嵌套的 AGENTS.md。子项目的 AGENTS.md 只写该子项目特有的内容,不重复根级内容。 + +## Important Rules + +- **控制长度**:AGENTS.md 建议 150 行以内,不要写成完整文档 +- **只写有用的**:不要填充模板中每个段落,省略不适用的 +- **面向 AI Agent**:内容是给 AI 看的,不需要"入门教程"级别的解释 +- **可执行的命令**:构建、测试、lint 等必须是可以直接复制执行的命令 +- **不要暴露敏感信息**:不要写 API key、密码、内部 URL 等 +- **中英文皆可**:跟随项目的主要语言(README 是中文就用中文) + +## Examples + +用户说:"帮我生成 AGENTS.md" + +→ 执行 Step 1-4,扫描项目后生成文件。 + +用户说:"更新一下 AGENTS.md" + +→ 先读取现有 AGENTS.md,结合项目当前状态更新过时的内容。 diff --git a/account/admin/skills/system/generate-image/.openakita-i18n.json b/account/admin/skills/system/generate-image/.openakita-i18n.json new file mode 100644 index 0000000..fde9fde --- /dev/null +++ b/account/admin/skills/system/generate-image/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "文生图", + "description": "根据提示词生成图片并保存为本地 PNG 文件,需要配置 DASHSCOPE_API_KEY。" + } +} diff --git a/account/admin/skills/system/generate-image/SKILL.md b/account/admin/skills/system/generate-image/SKILL.md new file mode 100644 index 0000000..dcaec44 --- /dev/null +++ b/account/admin/skills/system/generate-image/SKILL.md @@ -0,0 +1,66 @@ +--- +name: generate-image +description: 文生图(Qwen-Image)。根据提示词生成图片并保存为本地 PNG 文件;需要配置 DASHSCOPE_API_KEY,可选配置 DASHSCOPE_IMAGE_API_URL。生成后可用 deliver_artifacts 发送到 IM。 +system: true +handler: system +tool-name: generate_image +category: System +priority: high +--- + +# generate_image - 文生图(Qwen-Image) + +使用通义百炼 Qwen-Image 系列模型(如 `qwen-image-max`)根据提示词生成图片,并自动下载保存为本地 PNG 文件。 + +## 前置条件 + +- 环境变量:`DASHSCOPE_API_KEY`(与通义其它模型共用) +- 可选:`DASHSCOPE_IMAGE_API_URL` + - 北京地域(默认):`https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` + - 新加坡地域:`https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation` + +(API 参考:`https://help.aliyun.com/zh/model-studio/qwen-image-api`) + +## 用法 + +```json +{ + "prompt": "一张极简风格的产品海报,白色背景,中心是一只橘猫的线稿,标题“OPENAKITA”", + "model": "qwen-image-max", + "size": "1328*1328", + "prompt_extend": true, + "watermark": false +} +``` + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|---|---|---|---| +| prompt | string | 是 | 正向提示词 | +| model | string | 否 | 模型名,默认 `qwen-image-max` | +| negative_prompt | string | 否 | 反向提示词 | +| size | string | 否 | 分辨率,格式 `宽*高`,默认 `1664*928` | +| prompt_extend | boolean | 否 | 是否开启提示词智能改写,默认 true | +| watermark | boolean | 否 | 是否加水印,默认 false | +| seed | integer | 否 | 随机种子 | +| output_path | string | 否 | 输出路径;不填会落到 `data/generated_images/` | + +## 返回值 + +返回 JSON 字符串,包含: +- `saved_to`: 本地 PNG 路径 +- `image_url`: 临时图片 URL(通常 24 小时有效) + +## 发送到 IM(可选) + +生成后如需发送图片到聊天,请调用 `deliver_artifacts`: + +```json +{ + "artifacts": [ + {"type": "image", "path": "data/generated_images/xxx.png", "caption": "生成的图片"} + ] +} +``` + diff --git a/account/admin/skills/system/get-chat-history/.openakita-i18n.json b/account/admin/skills/system/get-chat-history/.openakita-i18n.json new file mode 100644 index 0000000..c5b16ba --- /dev/null +++ b/account/admin/skills/system/get-chat-history/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "获取聊天记录", + "description": "获取当前聊天历史,包括用户消息、回复和系统通知。" + } +} diff --git a/account/admin/skills/system/get-chat-history/SKILL.md b/account/admin/skills/system/get-chat-history/SKILL.md new file mode 100644 index 0000000..fab0ea3 --- /dev/null +++ b/account/admin/skills/system/get-chat-history/SKILL.md @@ -0,0 +1,35 @@ +--- +name: get-chat-history +description: Get current chat history including user messages, your replies, and system task notifications. When user says 'check previous messages' or 'what did I just send', use this tool. +system: true +handler: im_channel +tool-name: get_chat_history +category: IM Channel +--- + +# Get Chat History + +获取当前聊天的历史消息记录。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| limit | integer | 否 | 获取最近多少条消息,默认 20 | +| include_system | boolean | 否 | 是否包含系统消息(如任务通知),默认 True | + +## Returns + +- 用户发送的消息 +- 你之前的回复 +- 系统任务发送的通知 + +## When to Use + +- 用户说"看看之前的消息" +- 用户说"刚才发的什么" +- 需要回顾对话上下文 + +## Related Skills + +- `deliver-artifacts`: 发送附件给用户 diff --git a/account/admin/skills/system/get-image-file/.openakita-i18n.json b/account/admin/skills/system/get-image-file/.openakita-i18n.json new file mode 100644 index 0000000..af3de62 --- /dev/null +++ b/account/admin/skills/system/get-image-file/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "获取图片文件", + "description": "获取用户发送的图片的本地文件路径,用于处理或分析图片内容。" + } +} diff --git a/account/admin/skills/system/get-image-file/SKILL.md b/account/admin/skills/system/get-image-file/SKILL.md new file mode 100644 index 0000000..6af15c2 --- /dev/null +++ b/account/admin/skills/system/get-image-file/SKILL.md @@ -0,0 +1,27 @@ +--- +name: get-image-file +description: Get local file path of image sent by user. When user sends image, system auto-downloads it. When you need to process user's image or analyze image content. +system: true +handler: im_channel +tool-name: get_image_file +category: IM Channel +--- + +# Get Image File + +获取用户发送的图片的本地文件路径。 + +## Parameters + +无参数。 + +## Workflow + +1. 用户发送图片 +2. 系统自动下载到本地 +3. 使用此工具获取文件路径 + +## Related Skills + +- `get-voice-file`: 获取语音文件 +- `deliver-artifacts`: 发送文件给用户 diff --git a/account/admin/skills/system/get-mcp-instructions/.openakita-i18n.json b/account/admin/skills/system/get-mcp-instructions/.openakita-i18n.json new file mode 100644 index 0000000..fb8ed12 --- /dev/null +++ b/account/admin/skills/system/get-mcp-instructions/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "MCP 使用说明", + "description": "获取 MCP 服务器的详细使用说明(INSTRUCTIONS.md),了解服务器完整功能。" + } +} diff --git a/account/admin/skills/system/get-mcp-instructions/SKILL.md b/account/admin/skills/system/get-mcp-instructions/SKILL.md new file mode 100644 index 0000000..e098eab --- /dev/null +++ b/account/admin/skills/system/get-mcp-instructions/SKILL.md @@ -0,0 +1,29 @@ +--- +name: get-mcp-instructions +description: Get MCP server detailed usage instructions (INSTRUCTIONS.md). When you need to understand server full capabilities or learn server-specific usage patterns. +system: true +handler: mcp +tool-name: get_mcp_instructions +category: MCP +--- + +# Get MCP Instructions + +获取 MCP 服务器的详细使用说明。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| server | string | 是 | 服务器标识符 | + +## Returns + +- 服务器功能说明 +- 工具使用指南 +- 示例和最佳实践 + +## Related Skills + +- `list-mcp-servers`: 列出服务器 +- `call-mcp-tool`: 调用工具 diff --git a/account/admin/skills/system/get-memory-stats/.openakita-i18n.json b/account/admin/skills/system/get-memory-stats/.openakita-i18n.json new file mode 100644 index 0000000..a81edf8 --- /dev/null +++ b/account/admin/skills/system/get-memory-stats/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "记忆统计", + "description": "获取记忆系统统计信息,包括记忆总数和按类型的分布。" + } +} diff --git a/account/admin/skills/system/get-memory-stats/SKILL.md b/account/admin/skills/system/get-memory-stats/SKILL.md new file mode 100644 index 0000000..aed059b --- /dev/null +++ b/account/admin/skills/system/get-memory-stats/SKILL.md @@ -0,0 +1,29 @@ +--- +name: get-memory-stats +description: Get memory system statistics including total count and breakdown by type. When you need to check memory usage or understand memory distribution. +system: true +handler: memory +tool-name: get_memory_stats +category: Memory +--- + +# Get Memory Stats + +获取记忆系统统计信息。 + +## Parameters + +无参数。 + +## Returns + +- 总记忆数量 +- 今日会话数 +- 待处理会话数 +- 按类型分布 +- 按优先级分布 + +## Related Skills + +- `add-memory`: 添加记忆 +- `search-memory`: 搜索记忆 diff --git a/account/admin/skills/system/get-plan-status/.openakita-i18n.json b/account/admin/skills/system/get-plan-status/.openakita-i18n.json new file mode 100644 index 0000000..c9e1ef0 --- /dev/null +++ b/account/admin/skills/system/get-plan-status/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "查看计划进度", + "description": "获取当前计划的执行状态,显示所有步骤及其完成情况。" + } +} diff --git a/account/admin/skills/system/get-plan-status/SKILL.md b/account/admin/skills/system/get-plan-status/SKILL.md new file mode 100644 index 0000000..29e8c1e --- /dev/null +++ b/account/admin/skills/system/get-plan-status/SKILL.md @@ -0,0 +1,29 @@ +--- +name: get-plan-status +description: Get the current plan execution status. Shows all steps and their completion status. Use to check progress during multi-step task execution. +system: true +handler: plan +tool-name: get_plan_status +category: Plan +--- + +# Get Plan Status + +获取当前计划的执行状态。 + +## Parameters + +无需参数。 + +## Returns + +- 计划总览(task_summary) +- 各步骤状态 +- 已完成/待执行数量 +- 执行日志 + +## Related Skills + +- `create-plan`: 创建计划 +- `update-plan-step`: 更新步骤状态 +- `complete-plan`: 完成计划 diff --git a/account/admin/skills/system/get-session-logs/.openakita-i18n.json b/account/admin/skills/system/get-session-logs/.openakita-i18n.json new file mode 100644 index 0000000..a0f0bbf --- /dev/null +++ b/account/admin/skills/system/get-session-logs/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "会话日志", + "description": "获取当前会话的系统日志,用于排查命令执行失败、错误或理解操作结果。" + } +} diff --git a/account/admin/skills/system/get-session-logs/SKILL.md b/account/admin/skills/system/get-session-logs/SKILL.md new file mode 100644 index 0000000..93bcd25 --- /dev/null +++ b/account/admin/skills/system/get-session-logs/SKILL.md @@ -0,0 +1,31 @@ +--- +name: get-session-logs +description: Get current session system logs. IMPORTANT - when commands fail, encounter errors, or need to understand previous operation results, call this tool. Logs contain command details, error info, system status. +system: true +handler: system +tool-name: get_session_logs +category: System +--- + +# Get Session Logs + +获取当前会话的系统日志。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| count | integer | 否 | 返回的日志条数,默认 20,最大 200 | +| level | string | 否 | 过滤日志级别:DEBUG, INFO, WARNING, ERROR | + +## When to Use + +1. 命令返回错误码 +2. 操作没有预期效果 +3. 需要了解之前发生了什么 + +## Returns + +- 命令执行详情 +- 错误信息 +- 系统状态 diff --git a/account/admin/skills/system/get-skill-info/.openakita-i18n.json b/account/admin/skills/system/get-skill-info/.openakita-i18n.json new file mode 100644 index 0000000..9733c8d --- /dev/null +++ b/account/admin/skills/system/get-skill-info/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "技能详情", + "description": "获取技能的详细使用说明和指南,了解技能的功能和使用方法。" + } +} diff --git a/account/admin/skills/system/get-skill-info/SKILL.md b/account/admin/skills/system/get-skill-info/SKILL.md new file mode 100644 index 0000000..b784ba1 --- /dev/null +++ b/account/admin/skills/system/get-skill-info/SKILL.md @@ -0,0 +1,33 @@ +--- +name: get-skill-info +description: Get skill detailed instructions and usage guide (Level 2 disclosure). When you need to understand how to use a skill, check skill capabilities, or learn skill parameters. +system: true +handler: skills +tool-name: get_skill_info +category: Skills Management +--- + +# Get Skill Info + +获取技能的详细信息和指令(Level 2 披露)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| skill_name | string | 是 | 技能名称 | + +## Returns + +- 完整的 SKILL.md 内容(使用说明和指令) +- 参考文档列表(如有) + +## Important + +大多数外部技能(xlsx, docx, pptx, pdf 等)是**指令型技能**,没有预置脚本。 +读取指令后应按照指令编写代码,通过 `run_shell` 执行,而非调用 `run_skill_script`。 + +## Related Skills + +- `list-skills`: 列出所有技能 +- `run-shell`: 执行按技能指令编写的代码 diff --git a/account/admin/skills/system/get-skill-reference/.openakita-i18n.json b/account/admin/skills/system/get-skill-reference/.openakita-i18n.json new file mode 100644 index 0000000..1edf2f1 --- /dev/null +++ b/account/admin/skills/system/get-skill-reference/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "技能参考文档", + "description": "获取技能的参考文档,提供详细技术文档、示例和高级用法说明。" + } +} diff --git a/account/admin/skills/system/get-skill-reference/SKILL.md b/account/admin/skills/system/get-skill-reference/SKILL.md new file mode 100644 index 0000000..41e293d --- /dev/null +++ b/account/admin/skills/system/get-skill-reference/SKILL.md @@ -0,0 +1,24 @@ +--- +name: get-skill-reference +description: Get skill reference documentation for additional guidance. When you need to get detailed technical docs, find examples, or understand advanced usage. +system: true +handler: skills +tool-name: get_skill_reference +category: Skills Management +--- + +# Get Skill Reference + +获取技能的参考文档。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| skill_name | string | 是 | 技能名称 | +| ref_name | string | 否 | 参考文档名称,默认 REFERENCE.md | + +## Related Skills + +- `get-skill-info`: 获取主要说明 +- `run-shell`: 执行按技能指令编写的代码 diff --git a/account/admin/skills/system/get-tool-info/.openakita-i18n.json b/account/admin/skills/system/get-tool-info/.openakita-i18n.json new file mode 100644 index 0000000..6992562 --- /dev/null +++ b/account/admin/skills/system/get-tool-info/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "工具详情", + "description": "获取系统工具的详细参数定义,了解工具的使用方法和参数说明。" + } +} diff --git a/account/admin/skills/system/get-tool-info/SKILL.md b/account/admin/skills/system/get-tool-info/SKILL.md new file mode 100644 index 0000000..5ca59ef --- /dev/null +++ b/account/admin/skills/system/get-tool-info/SKILL.md @@ -0,0 +1,28 @@ +--- +name: get-tool-info +description: Get system tool detailed parameter definition (Level 2 disclosure). When you need to understand unfamiliar tool usage, check tool parameters, or learn tool examples. Call before using unfamiliar tools. +system: true +handler: system +tool-name: get_tool_info +category: System +--- + +# Get Tool Info + +获取系统工具的详细参数定义(Level 2 披露)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| tool_name | string | 是 | 工具名称 | + +## When to Use + +- 了解不熟悉的工具用法 +- 查看工具参数 +- 学习工具示例 + +## Tip + +在调用不熟悉的工具前,先用此工具了解其完整用法、参数说明和示例。 diff --git a/account/admin/skills/system/get-user-profile/.openakita-i18n.json b/account/admin/skills/system/get-user-profile/.openakita-i18n.json new file mode 100644 index 0000000..e3e3edf --- /dev/null +++ b/account/admin/skills/system/get-user-profile/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "获取用户画像", + "description": "获取当前用户的画像摘要,了解用户偏好和上下文信息。" + } +} diff --git a/account/admin/skills/system/get-user-profile/SKILL.md b/account/admin/skills/system/get-user-profile/SKILL.md new file mode 100644 index 0000000..063060b --- /dev/null +++ b/account/admin/skills/system/get-user-profile/SKILL.md @@ -0,0 +1,27 @@ +--- +name: get-user-profile +description: Get current user profile summary to understand user's preferences and context. When you need to check known user info or personalize responses. +system: true +handler: profile +tool-name: get_user_profile +category: User Profile +--- + +# Get User Profile + +获取当前用户档案信息摘要。 + +## Parameters + +无参数。 + +## Returns + +- 已填写的档案项 +- 用户偏好设置 +- 工作相关信息 + +## Related Skills + +- `update-user-profile`: 更新档案 +- `skip-profile-question`: 跳过问题 diff --git a/account/admin/skills/system/get-voice-file/.openakita-i18n.json b/account/admin/skills/system/get-voice-file/.openakita-i18n.json new file mode 100644 index 0000000..523af5d --- /dev/null +++ b/account/admin/skills/system/get-voice-file/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "获取语音文件", + "description": "获取用户发送的语音消息的本地文件路径,用于处理语音内容。" + } +} diff --git a/account/admin/skills/system/get-voice-file/SKILL.md b/account/admin/skills/system/get-voice-file/SKILL.md new file mode 100644 index 0000000..57dc08c --- /dev/null +++ b/account/admin/skills/system/get-voice-file/SKILL.md @@ -0,0 +1,28 @@ +--- +name: get-voice-file +description: Get local file path of voice message sent by user. When user sends voice message, system auto-downloads it. When you need to process user's voice message or transcribe voice to text. +system: true +handler: im_channel +tool-name: get_voice_file +category: IM Channel +--- + +# Get Voice File + +获取用户发送的语音消息的本地文件路径。 + +## Parameters + +无参数。 + +## Workflow + +1. 用户发送语音消息 +2. 系统自动下载到本地 +3. 使用此工具获取文件路径 +4. 用语音识别脚本处理 + +## Related Skills + +- `get-image-file`: 获取图片文件 +- `deliver-artifacts`: 发送文件给用户 diff --git a/account/admin/skills/system/healthcheck_dingtalk.md b/account/admin/skills/system/healthcheck_dingtalk.md new file mode 100644 index 0000000..30e3fc0 --- /dev/null +++ b/account/admin/skills/system/healthcheck_dingtalk.md @@ -0,0 +1,29 @@ +# DingTalk 健康检查记录 + +## 背景 +- 报错:`openakita.channels.adapters.dingtalk` 发送图片失败,服务端返回“robot 不存在”。 +- 常见原因:`robotCode` 配置错误/为空、机器人未创建或未启用、应用与群绑定不匹配。 + +## 当前本地配置发现(基于 `.env`) +- DINGTALK_ENABLED = true +- DINGTALK_CLIENT_ID = dingo7jnkd1c3hquoacu +- DINGTALK_CLIENT_SECRET = (已配置) + +⚠️ 说明:OpenAkita 当前钉钉适配器将 `robotCode` 直接使用 `app_key`(即 DINGTALK_CLIENT_ID)。若你的机器人 `robotCode` 并非该值,则会导致 “robot 不存在”。 + +## 健康检查 +由于缺少可用的 webhook / openConversationId / userId 等目标参数(本仓库配置中未发现),无法对“发送消息/图片”接口做真实探测。 + +建议人工补充以下至少一项后重试: +1. 任一会话的 `sessionWebhook`(从钉钉机器人回调消息中可获取),或 +2. 群聊的 `openConversationId`,或 +3. 单聊目标 `userId`。 + +可用于探测的接口: +- OAuth2 token: `POST https://api.dingtalk.com/v1.0/oauth2/accessToken`(仅验证 appKey/appSecret 是否有效) +- 单聊发送:`POST https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend` +- 群聊发送:`POST https://api.dingtalk.com/v1.0/robot/groupMessages/send` + +## 处理结论 +- 本次未对核心代码做修改(遵循限制)。 +- 需要人工确认并提供正确的 `robotCode`(通常为机器人编码,不一定等于 appKey)以及可投递目标(userId/openConversationId 或 sessionWebhook)。 diff --git a/account/admin/skills/system/import-agent/SKILL.md b/account/admin/skills/system/import-agent/SKILL.md new file mode 100644 index 0000000..b67613b --- /dev/null +++ b/account/admin/skills/system/import-agent/SKILL.md @@ -0,0 +1,31 @@ +--- +name: import-agent +description: Import an Agent from a .akita-agent package file. Installs the Agent profile and any bundled skills to the local system. +system: true +handler: agent_package +tool-name: import_agent +category: Agent Package +--- + +# Import Agent + +从 `.akita-agent` 包文件导入 Agent,安装 Agent 配置和捆绑技能到本地。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| package_path | string | 是 | .akita-agent 包文件路径 | +| force | boolean | 否 | 如果 ID 冲突是否强制覆盖(默认 false) | + +## Import Behavior + +1. 校验包格式和安全性 +2. 安装捆绑技能到 `skills/custom/` 目录 +3. 创建 Agent Profile(type 强制为 custom) +4. 如果 ID 冲突且未 force,自动追加后缀 + +## Related Skills + +- `export-agent`: 导出 Agent 包 +- `inspect-agent-package`: 导入前预览包内容 diff --git a/account/admin/skills/system/inspect-agent-package/SKILL.md b/account/admin/skills/system/inspect-agent-package/SKILL.md new file mode 100644 index 0000000..7021201 --- /dev/null +++ b/account/admin/skills/system/inspect-agent-package/SKILL.md @@ -0,0 +1,32 @@ +--- +name: inspect-agent-package +description: Preview the contents of a .akita-agent package file without installing it. Shows manifest, profile, bundled skills, and validation status. +system: true +handler: agent_package +tool-name: inspect_agent_package +category: Agent Package +--- + +# Inspect Agent Package + +预览 `.akita-agent` 包文件内容,不执行安装。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| package_path | string | 是 | .akita-agent 包文件路径 | + +## Returns + +返回包详情: +- `manifest`: 包元数据 +- `profile`: Agent 配置 +- `bundled_skills`: 捆绑技能列表 +- `validation_errors`: 校验错误(如有) +- `id_conflict`: 是否与本地已有 Agent 冲突 +- `package_size`: 包文件大小 + +## Related Skills + +- `import-agent`: 确认后导入 diff --git a/account/admin/skills/system/install-hub-agent/SKILL.md b/account/admin/skills/system/install-hub-agent/SKILL.md new file mode 100644 index 0000000..05bfdef --- /dev/null +++ b/account/admin/skills/system/install-hub-agent/SKILL.md @@ -0,0 +1,57 @@ +--- +name: install-hub-agent +description: Download and install an Agent from the OpenAkita Platform Agent Store +system: true +handler: agent_hub +tool-name: install_hub_agent +category: Platform +--- + +# install-hub-agent + +Download and install an Agent from the OpenAkita Platform Agent Store to the local system. + +## When to Use + +- User wants to install a specific Agent from the hub +- User says "安装这个 Agent" after browsing search results +- User provides an Agent ID to install + +## Workflow + +1. (Optional) Call `search_hub_agents` first to find the Agent +2. (Optional) Call `get_hub_agent_detail` to preview Agent details +3. Call `install_hub_agent` with the `agent_id` +4. The system will: + - Download the `.akita-agent` package from the platform + - Extract and install bundled skills (version-aware, skips if same/newer exists locally) + - Fetch required external skills from their original GitHub repos + - Register the Agent profile locally + - Auto-reload skills so the Agent is immediately usable + +## Tools + +### install_hub_agent +| Parameter | Required | Description | +|-----------|----------|-------------| +| `agent_id` | Yes | The platform Agent ID (from search results) | +| `force` | No | Force overwrite if local ID conflict (default: false) | + +### get_hub_agent_detail +| Parameter | Required | Description | +|-----------|----------|-------------| +| `agent_id` | Yes | The platform Agent ID to inspect | + +## Important Notes + +- Installed Agents appear in the local Agent list immediately +- Bundled skills go to `skills/custom/`, external skills go to `skills/community/` +- Skills are version-deduplicated: if a newer version already exists locally, it is kept +- Each installed skill gets a `.openakita-origin.json` tracking its source and version +- The Agent's `hub_source` field records where it came from + +## Fallback + +If the platform is unavailable, the user can still: +- Import Agents from `.akita-agent` files using `import_agent` +- Export local Agents using `export_agent` diff --git a/account/admin/skills/system/install-skill/.openakita-i18n.json b/account/admin/skills/system/install-skill/.openakita-i18n.json new file mode 100644 index 0000000..0e1189c --- /dev/null +++ b/account/admin/skills/system/install-skill/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "安装技能", + "description": "从 URL 或 Git 仓库安装技能到本地 skills/ 目录,支持 GitHub 简写格式。" + } +} diff --git a/account/admin/skills/system/install-skill/SKILL.md b/account/admin/skills/system/install-skill/SKILL.md new file mode 100644 index 0000000..2488c88 --- /dev/null +++ b/account/admin/skills/system/install-skill/SKILL.md @@ -0,0 +1,35 @@ +--- +name: install-skill +description: Install skill from URL or Git repository to local skills/ directory. When you need to add new skill from GitHub or install SKILL.md from URL. Supports Git repos and single SKILL.md files. +system: true +handler: skills +tool-name: install_skill +category: Skills Management +--- + +# Install Skill + +从 URL 或 Git 仓库安装技能到本地 skills/ 目录。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| source | string | 是 | Git 仓库 URL 或 SKILL.md 文件 URL | +| name | string | 否 | 技能名称(可选,自动从 SKILL.md 提取) | +| subdir | string | 否 | Git 仓库中技能所在的子目录路径 | +| extra_files | array | 否 | 额外需要下载的文件 URL 列表 | + +## Supported Sources + +1. **Git 仓库** (如 https://github.com/user/repo) + - 自动克隆仓库并查找 SKILL.md + - 支持指定子目录路径 + +2. **单个 SKILL.md 文件 URL** + - 创建规范目录结构(scripts/, references/, assets/) + +## Related Skills + +- `list-skills`: 查看已安装技能 +- `find-skills`: 搜索可用技能 diff --git a/account/admin/skills/system/install-store-skill/SKILL.md b/account/admin/skills/system/install-store-skill/SKILL.md new file mode 100644 index 0000000..5f625a1 --- /dev/null +++ b/account/admin/skills/system/install-store-skill/SKILL.md @@ -0,0 +1,59 @@ +--- +name: install-store-skill +description: Install a Skill from the OpenAkita Platform Skill Store +system: true +handler: skill_store +tool-name: install_store_skill +category: Platform +--- + +# install-store-skill + +Install a Skill from the OpenAkita Platform Skill Store to the local system. + +## When to Use + +- User wants to install a specific Skill from the store +- User says "安装这个技能" after browsing search results +- User provides a Skill ID to install + +## Workflow + +1. (Optional) Call `search_store_skills` first to find the Skill +2. (Optional) Call `get_store_skill_detail` to preview details, license, ratings +3. Call `install_store_skill` with the `skill_id` +4. The system will: + - Fetch the Skill's install URL from the platform + - Clone the Skill from its original GitHub repository + - Auto-reload skills so the Skill is immediately available + +## Tools + +### install_store_skill +| Parameter | Required | Description | +|-----------|----------|-------------| +| `skill_id` | Yes | The platform Skill ID (from search results) | + +### get_store_skill_detail +| Parameter | Required | Description | +|-----------|----------|-------------| +| `skill_id` | Yes | The platform Skill ID to inspect | + +### submit_skill_repo +| Parameter | Required | Description | +|-----------|----------|-------------| +| `repo_url` | Yes | GitHub repository URL to submit as a new Skill | + +## Important Notes + +- Skills are installed from their **original GitHub repository**, not redistributed by the platform +- Each skill's open-source license applies — check the license before using in production +- After installation, the Skill is auto-loaded and immediately usable +- If a skill with the same name already exists locally, it will be updated + +## Fallback + +If the platform is unavailable, the user can still: +- Install skills directly from GitHub using `install_skill` +- Browse and install from skills.sh marketplace via Setup Center +- Manage local skills using `list_skills`, `enable_skill`, `disable_skill` diff --git a/account/admin/skills/system/list-directory/.openakita-i18n.json b/account/admin/skills/system/list-directory/.openakita-i18n.json new file mode 100644 index 0000000..5a27fa3 --- /dev/null +++ b/account/admin/skills/system/list-directory/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "列出目录", + "description": "列出目录内容,包括文件和子目录,用于浏览目录结构和查找文件。" + } +} diff --git a/account/admin/skills/system/list-directory/SKILL.md b/account/admin/skills/system/list-directory/SKILL.md new file mode 100644 index 0000000..527f2cc --- /dev/null +++ b/account/admin/skills/system/list-directory/SKILL.md @@ -0,0 +1,41 @@ +--- +name: list-directory +description: List directory contents including files and subdirectories. When you need to explore directory structure, find specific files, or check what exists in a folder. +system: true +handler: filesystem +tool-name: list_directory +category: File System +--- + +# List Directory + +列出目录内容。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| path | string | 是 | 目录路径 | + +## Returns + +- 文件名和类型 +- 文件大小 +- 修改时间 + +## Examples + +**列出当前目录**: +```json +{"path": "."} +``` + +**列出指定目录**: +```json +{"path": "/home/user/documents"} +``` + +## Related Skills + +- `read-file`: 读取文件内容 +- `write-file`: 写入文件 diff --git a/account/admin/skills/system/list-exportable-agents/SKILL.md b/account/admin/skills/system/list-exportable-agents/SKILL.md new file mode 100644 index 0000000..bc101cc --- /dev/null +++ b/account/admin/skills/system/list-exportable-agents/SKILL.md @@ -0,0 +1,29 @@ +--- +name: list-exportable-agents +description: List all Agent profiles that can be exported as .akita-agent packages. Shows both system and custom agents. +system: true +handler: agent_package +tool-name: list_exportable_agents +category: Agent Package +--- + +# List Exportable Agents + +列出所有可导出的 Agent,包括系统预设和自定义 Agent。 + +## Parameters + +无参数。 + +## Returns + +返回 Agent 列表,每项包含: +- `id`: Agent ID +- `name`: 显示名称 +- `type`: 类型(system/custom) +- `category`: 分类 +- `skills_count`: 技能数量 + +## Related Skills + +- `export-agent`: 导出指定 Agent diff --git a/account/admin/skills/system/list-mcp-servers/.openakita-i18n.json b/account/admin/skills/system/list-mcp-servers/.openakita-i18n.json new file mode 100644 index 0000000..e58434e --- /dev/null +++ b/account/admin/skills/system/list-mcp-servers/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "MCP 服务器列表", + "description": "列出所有已配置的 MCP 服务器及其连接状态。" + } +} diff --git a/account/admin/skills/system/list-mcp-servers/SKILL.md b/account/admin/skills/system/list-mcp-servers/SKILL.md new file mode 100644 index 0000000..de1641e --- /dev/null +++ b/account/admin/skills/system/list-mcp-servers/SKILL.md @@ -0,0 +1,28 @@ +--- +name: list-mcp-servers +description: List all configured MCP servers and their connection status. When you need to check available MCP servers or verify server connections. +system: true +handler: mcp +tool-name: list_mcp_servers +category: MCP +--- + +# List MCP Servers + +列出所有配置的 MCP 服务器及其连接状态。 + +## Parameters + +无参数。 + +## Returns + +- 服务器标识符 +- 服务器名称 +- 连接状态 +- 可用工具数量 + +## Related Skills + +- `call-mcp-tool`: 调用 MCP 工具 +- `get-mcp-instructions`: 获取使用说明 diff --git a/account/admin/skills/system/list-scheduled-tasks/.openakita-i18n.json b/account/admin/skills/system/list-scheduled-tasks/.openakita-i18n.json new file mode 100644 index 0000000..d7714ca --- /dev/null +++ b/account/admin/skills/system/list-scheduled-tasks/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "定时任务列表", + "description": "列出所有定时任务,包括 ID、名称、类型、状态和下次执行时间。" + } +} diff --git a/account/admin/skills/system/list-scheduled-tasks/SKILL.md b/account/admin/skills/system/list-scheduled-tasks/SKILL.md new file mode 100644 index 0000000..f490602 --- /dev/null +++ b/account/admin/skills/system/list-scheduled-tasks/SKILL.md @@ -0,0 +1,44 @@ +--- +name: list-scheduled-tasks +description: List all scheduled tasks with their ID, name, type, status, and next execution time. When you need to check existing tasks, find task ID for cancel/update, or verify task creation. +system: true +handler: scheduled +tool-name: list_scheduled_tasks +category: Scheduled Tasks +--- + +# List Scheduled Tasks + +列出所有定时任务。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| enabled_only | boolean | 否 | 是否只列出启用的任务,默认 false | + +## Returns + +- 任务 ID +- 名称 +- 类型(reminder/task) +- 状态(enabled/disabled) +- 下次执行时间 + +## Examples + +**列出所有任务**: +```json +{} +``` + +**只列出启用的任务**: +```json +{"enabled_only": true} +``` + +## Related Skills + +- `schedule-task`: 创建新任务 +- `cancel-scheduled-task`: 取消任务 +- `update-scheduled-task`: 更新任务设置 diff --git a/account/admin/skills/system/list-skills/.openakita-i18n.json b/account/admin/skills/system/list-skills/.openakita-i18n.json new file mode 100644 index 0000000..31db659 --- /dev/null +++ b/account/admin/skills/system/list-skills/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "列出技能", + "description": "列出所有已安装的技能,查看可用技能或查找适合任务的技能。" + } +} diff --git a/account/admin/skills/system/list-skills/SKILL.md b/account/admin/skills/system/list-skills/SKILL.md new file mode 100644 index 0000000..8cf8f2b --- /dev/null +++ b/account/admin/skills/system/list-skills/SKILL.md @@ -0,0 +1,28 @@ +--- +name: list-skills +description: List all installed skills following Agent Skills specification. When you need to check available skills, find skill for a task, or verify skill installation. +system: true +handler: skills +tool-name: list_skills +category: Skills Management +--- + +# List Skills + +列出已安装的技能(遵循 Agent Skills 规范)。 + +## Parameters + +无参数。 + +## Returns + +- 技能名称 +- 技能描述 +- 是否可自动调用 +- 系统技能 vs 外部技能标识 + +## Related Skills + +- `get-skill-info`: 获取技能详情 +- `install-skill`: 安装新技能 diff --git a/account/admin/skills/system/load-skill/.openakita-i18n.json b/account/admin/skills/system/load-skill/.openakita-i18n.json new file mode 100644 index 0000000..cd4cd4e --- /dev/null +++ b/account/admin/skills/system/load-skill/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "加载技能", + "description": "从 skills/ 目录加载新创建的技能,使其立即可用。" + } +} diff --git a/account/admin/skills/system/load-skill/SKILL.md b/account/admin/skills/system/load-skill/SKILL.md new file mode 100644 index 0000000..f02d7a4 --- /dev/null +++ b/account/admin/skills/system/load-skill/SKILL.md @@ -0,0 +1,43 @@ +--- +name: load-skill +description: Load a newly created skill from skills/ directory to make it immediately available +system: true +handler: skills +tool-name: load_skill +category: skills-management +--- + +# load-skill + +加载新创建的技能到系统中,使其立即可用。 + +## 使用场景 + +- 使用 `skill-creator` 创建技能后 +- 手动在 `skills/` 目录创建技能后 +- 需要立即使用新技能时 + +## 使用方法 + +``` +load_skill(skill_name="my-new-skill") +``` + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| skill_name | string | 是 | 技能名称(即 skills/ 下的目录名)| + +## 完整工作流 + +1. 使用 `skill-creator` 技能创建 SKILL.md +2. 将文件保存到 `skills/<skill-name>/SKILL.md` +3. 调用 `load_skill("<skill-name>")` 加载技能 +4. 技能立即可用 + +## 注意事项 + +- 技能目录必须包含有效的 `SKILL.md` 文件 +- 如果技能已存在,请使用 `reload_skill` 重新加载 +- 加载成功后,技能会出现在 `list_skills` 列表中 diff --git a/account/admin/skills/system/news-search/.openakita-i18n.json b/account/admin/skills/system/news-search/.openakita-i18n.json new file mode 100644 index 0000000..c85ec63 --- /dev/null +++ b/account/admin/skills/system/news-search/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "新闻搜索", + "description": "使用 DuckDuckGo 搜索新闻,查找最新新闻、时事动态或突发事件。" + } +} diff --git a/account/admin/skills/system/news-search/SKILL.md b/account/admin/skills/system/news-search/SKILL.md new file mode 100644 index 0000000..1cdb247 --- /dev/null +++ b/account/admin/skills/system/news-search/SKILL.md @@ -0,0 +1,38 @@ +--- +name: news-search +description: Search news using DuckDuckGo. Use when you need to find recent news articles, current events, or breaking news. Returns titles, sources, dates, URLs, and excerpts. +system: true +handler: web_search +tool-name: news_search +category: Web Search +--- + +# News Search + +使用 DuckDuckGo 搜索新闻,获取最新资讯。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| query | string | 是 | 搜索关键词 | +| max_results | integer | 否 | 最大结果数(1-20,默认 5) | +| region | string | 否 | 地区代码(wt-wt 全球) | +| safesearch | string | 否 | 安全搜索(on/moderate/off) | +| timelimit | string | 否 | 时间范围(d=一天, w=一周, m=一月) | + +## Examples + +**搜索新闻**: +```json +{"query": "AI 最新进展", "max_results": 5} +``` + +**搜索今日新闻**: +```json +{"query": "科技", "timelimit": "d"} +``` + +## Related Skills + +- `web-search`: 搜索网页 diff --git a/account/admin/skills/system/platform-guide/SKILL.md b/account/admin/skills/system/platform-guide/SKILL.md new file mode 100644 index 0000000..28bf1ab --- /dev/null +++ b/account/admin/skills/system/platform-guide/SKILL.md @@ -0,0 +1,134 @@ +--- +name: platform-guide +description: "OpenAkita 平台使用指南:教你帮用户从 Agent Hub 和 Skill Store 搜索、安装 Agent 和 Skill" +system: true +category: Platform +--- + +# OpenAkita Platform Guide — AI 操作手册 + +> **核心原则**:当用户需要某种能力但本地没有时,你应该 **主动搜索平台**。 + +## 什么时候该用平台? + +- 用户说"帮我找一个 XX Agent / 技能 / Skill" +- 用户需要某种能力但本地没有对应的技能 +- 用户说"有没有现成的"、"市场上有吗"、"安装一个" +- 用户提到 Agent Hub、Skill Store、OpenAkita 平台 + +**注意**:平台是 **可选扩展**,离线时所有本地功能不受影响。 + +--- + +## Agent 安装三步走 + +当用户想从平台获取 Agent 时: + +**第 1 步 — 搜索** +``` +search_hub_agents(query="客服", category="customer_service") +``` +- 查看返回的 Agent 列表,注意每个 Agent 的 `id` + +**第 2 步 — 预览(推荐)** +``` +get_hub_agent_detail(agent_id="the-agent-id") +``` +- 查看描述、技能列表、评分、下载量 + +**第 3 步 — 安装** +``` +install_hub_agent(agent_id="the-agent-id") +``` +- 系统自动:下载包 → 解压技能 → 版本去重 → 注册 Agent → 热重载 +- 安装后 Agent **立刻可用** + +### 安装时发生了什么? +1. 下载 `.akita-agent` 包 +2. 打包的技能 → `skills/custom/`(版本去重:本地有更新版就跳过) +3. 外部依赖技能 → 从原始 GitHub 仓库拉取到 `skills/community/` +4. 每个技能写入 `.openakita-origin.json` 追踪来源 +5. Agent 配置注册到本地 → 技能自动重载 + +--- + +## Skill 安装三步走 + +当用户想从平台获取 Skill 时: + +**第 1 步 — 搜索** +``` +search_store_skills(query="翻译", trust_level="official") +``` +- 注意 `trustLevel`:official(官方)> certified(认证)> community(社区) + +**第 2 步 — 预览(推荐)** +``` +get_store_skill_detail(skill_id="the-skill-id") +``` +- 查看描述、开源协议、GitHub Stars、评分 + +**第 3 步 — 安装** +``` +install_store_skill(skill_id="the-skill-id") +``` +- 从原始 GitHub 仓库直接克隆(非平台重新分发) +- 安装后技能 **立刻可用** + +--- + +## 本地 Agent 导入导出(不需要平台) + +``` +list_exportable_agents() # 查看可导出的 +export_agent(profile_id="my-agent", version="1.0.0") # 导出 +inspect_agent_package(package_path="xxx.akita-agent") # 预览包 +import_agent(package_path="xxx.akita-agent") # 导入 +``` + +--- + +## 版本去重策略 + +| 场景 | 行为 | +|------|------| +| 本地有同名 skill 且版本 >= 新包中的版本 | **跳过**(保留本地更新版) | +| 新包中版本 > 本地版本 | **覆盖**(升级到新版) | +| 任一方无版本信息 | **覆盖**(安全起见) | + +--- + +## 平台离线时的替代方案 + +| 需求 | 替代方式 | +|------|----------| +| 找 Agent | 用 `.akita-agent` 文件导入 | +| 找 Skill | `install_skill` 从 GitHub 直接装;Setup Center 的 skills.sh 市场 | +| 共享 Agent | `export_agent` 导出文件分享 | + +--- + +## 全部平台工具速查 + +| 工具 | 用途 | +|------|------| +| `search_hub_agents` | 搜索平台上的 Agent | +| `get_hub_agent_detail` | 查看 Agent 详情 | +| `install_hub_agent` | 安装 Agent 到本地 | +| `search_store_skills` | 搜索平台上的 Skill | +| `get_store_skill_detail` | 查看 Skill 详情 | +| `install_store_skill` | 安装 Skill 到本地 | +| `submit_skill_repo` | 提交 GitHub 仓库为新 Skill | +| `export_agent` | 导出本地 Agent | +| `import_agent` | 导入 Agent 包 | +| `list_exportable_agents` | 列出可导出的 Agent | +| `inspect_agent_package` | 预览 Agent 包内容 | + +--- + +## 许可证合规 + +- 平台上的 Skill 从 **原始开源仓库** 拉取,非平台重新分发 +- Agent 包可能含 `LICENSE-3RD-PARTY.md` 列出外部依赖 +- 安装前应告知用户相关许可证 +- 侵权联系:zacon365@gmail.com diff --git a/account/admin/skills/system/publish-agent/SKILL.md b/account/admin/skills/system/publish-agent/SKILL.md new file mode 100644 index 0000000..4bb76c3 --- /dev/null +++ b/account/admin/skills/system/publish-agent/SKILL.md @@ -0,0 +1,32 @@ +--- +name: publish-agent +description: Publish a local Agent to the OpenAkita Platform Agent Store +version: 1.0.0 +--- + +# publish-agent + +Publish a local Agent to the OpenAkita Platform Agent Store. + +## Tools + +- publish_agent - Package and prepare a local Agent for publishing + +## Usage + +Use this skill when the user wants to: +- Share a local Agent to the community +- Publish an Agent to the OpenAkita hub +- Package an Agent for distribution + +## Parameters + +- profile_id (required): The local Agent profile ID to publish +- description (optional): Description for the platform listing +- category (optional): Category for the listing +- ags (optional): Tags for discoverability + +## Examples + +- "Publish my custom Agent to Hub" +- "Share this Agent to community" diff --git a/account/admin/skills/system/read-file/.openakita-i18n.json b/account/admin/skills/system/read-file/.openakita-i18n.json new file mode 100644 index 0000000..717f1e6 --- /dev/null +++ b/account/admin/skills/system/read-file/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "读取文件", + "description": "读取文本文件内容,用于查看文件内容、分析代码或获取配置信息。" + } +} diff --git a/account/admin/skills/system/read-file/SKILL.md b/account/admin/skills/system/read-file/SKILL.md new file mode 100644 index 0000000..f48878f --- /dev/null +++ b/account/admin/skills/system/read-file/SKILL.md @@ -0,0 +1,41 @@ +--- +name: read-file +description: Read file content for text files. When you need to check file content, analyze code or data, or get configuration values. +system: true +handler: filesystem +tool-name: read_file +category: File System +--- + +# Read File + +读取文件内容。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| path | string | 是 | 文件路径 | + +## Examples + +**读取配置文件**: +```json +{"path": "config.json"} +``` + +**读取代码文件**: +```json +{"path": "src/main.py"} +``` + +## Notes + +- 适用于文本文件 +- 使用 UTF-8 编码 +- 二进制文件需要特殊处理 + +## Related Skills + +- `write-file`: 写入文件 +- `list-directory`: 列出目录内容 diff --git a/account/admin/skills/system/reload-skill/.openakita-i18n.json b/account/admin/skills/system/reload-skill/.openakita-i18n.json new file mode 100644 index 0000000..5b6a123 --- /dev/null +++ b/account/admin/skills/system/reload-skill/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "重新加载技能", + "description": "重新加载已修改的技能,使 SKILL.md 或脚本的更改生效。" + } +} diff --git a/account/admin/skills/system/reload-skill/SKILL.md b/account/admin/skills/system/reload-skill/SKILL.md new file mode 100644 index 0000000..f333693 --- /dev/null +++ b/account/admin/skills/system/reload-skill/SKILL.md @@ -0,0 +1,42 @@ +--- +name: reload-skill +description: Reload an existing skill to apply changes after modifying SKILL.md or scripts +system: true +handler: skills +tool-name: reload_skill +category: skills-management +--- + +# reload-skill + +重新加载已存在的技能,以应用对 SKILL.md 或脚本的修改。 + +## 使用场景 + +- 修改了技能的 SKILL.md 后 +- 更新了技能的脚本后 +- 需要刷新技能配置时 + +## 使用方法 + +``` +reload_skill(skill_name="my-skill") +``` + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| skill_name | string | 是 | 技能名称 | + +## 工作原理 + +1. 卸载原有技能 +2. 重新解析 SKILL.md +3. 重新注册到系统 + +## 注意事项 + +- 只能重新加载已加载过的技能 +- 如果是新技能,请使用 `load_skill` +- 重新加载后,技能的所有修改立即生效 diff --git a/account/admin/skills/system/run-shell/.openakita-i18n.json b/account/admin/skills/system/run-shell/.openakita-i18n.json new file mode 100644 index 0000000..7f314a3 --- /dev/null +++ b/account/admin/skills/system/run-shell/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "执行命令", + "description": "执行 Shell 命令,用于系统操作、创建目录、运行脚本和安装软件包。" + } +} diff --git a/account/admin/skills/system/run-shell/SKILL.md b/account/admin/skills/system/run-shell/SKILL.md new file mode 100644 index 0000000..62c8da2 --- /dev/null +++ b/account/admin/skills/system/run-shell/SKILL.md @@ -0,0 +1,95 @@ +--- +name: run-shell +description: Execute shell commands for system operations, directory creation, and script execution. When you need to run system commands, execute scripts, install packages, or manage processes. Note - if commands fail consecutively, try different approaches. +system: true +handler: filesystem +tool-name: run_shell +category: File System +--- + +# Run Shell + +执行 Shell 命令。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| command | string | 是 | 要执行的 Shell 命令 | +| cwd | string | 否 | 工作目录(可选) | +| timeout | integer | 否 | 超时时间(秒),默认 60,范围 10-600 | + +## Examples + +**列出目录**: +```json +{"command": "ls -la"} +``` + +**安装依赖**: +```json +{"command": "pip install requests", "timeout": 300} +``` + +**在指定目录执行**: +```json +{"command": "npm install", "cwd": "/path/to/project"} +``` + +## Timeout Guidelines + +- 简单命令: 30-60 秒 +- 安装/下载: 300 秒 +- 长时间任务: 根据需要设置更长时间 + +## Windows PowerShell 指引(重要) + +### 转义保护 + +系统会自动将 PowerShell 命令通过 `-EncodedCommand`(Base64 UTF-16LE)编码执行, +避免 cmd.exe → PowerShell 的多层引号/特殊字符转义破坏。直接传入 PowerShell 命令即可。 + +### 何时使用 PowerShell vs Python 脚本 + +| 场景 | 推荐方式 | 原因 | +|------|----------|------| +| 简单系统查询(进程/服务/文件列表) | PowerShell cmdlet | `Get-Process`, `Get-ChildItem` 等一行搞定 | +| 复杂文本处理(正则、URL 提取、HTML/JSON 解析) | **Python 脚本** | 避免 PowerShell 正则 one-liner 的复杂性 | +| 批量文件操作(重命名、过滤、转换) | **Python 脚本** | 更可靠,不受 PowerShell 管道转义影响 | +| 网络下载/HTTP 请求 | **Python 脚本** | `requests`/`urllib` 比 `Invoke-WebRequest` 更灵活 | + +### 推荐的 Python 脚本模式 + +对于复杂文本处理任务,**务必**使用 `write_file` + `run_shell` 组合: + +``` +步骤 1: write_file 写入 data/temp/task_xxx.py +步骤 2: run_shell "python data/temp/task_xxx.py" +``` + +**禁止**:在 `run_shell` 中写包含复杂正则的 PowerShell one-liner,例如: +``` +# 禁止这种写法 +powershell -Command "Get-Content file.html | Select-String -Pattern '(?<=src=\")[^\"]+' | ForEach-Object { $_.Matches.Value } | Sort-Object -Unique | Out-File urls.txt" +``` + +应改为写 Python 脚本: +```python +import re +from pathlib import Path +html = Path("file.html").read_text(encoding="utf-8") +urls = sorted(set(re.findall(r'src="([^"]+)"', html))) +Path("urls.txt").write_text("\n".join(urls), encoding="utf-8") +``` + +## Notes + +- Windows 使用 PowerShell/cmd 命令(自动 EncodedCommand 编码) +- Linux/Mac 使用 bash 命令 +- 如果命令连续失败,请尝试不同的命令或方法 +- 失败时可调用 `get_session_logs` 查看详细日志 + +## Related Skills + +- `write-file`: 写入文件 +- `read-file`: 读取文件 diff --git a/account/admin/skills/system/run-skill-script/.openakita-i18n.json b/account/admin/skills/system/run-skill-script/.openakita-i18n.json new file mode 100644 index 0000000..075165f --- /dev/null +++ b/account/admin/skills/system/run-skill-script/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "运行技能脚本", + "description": "执行技能的脚本文件,运行技能功能或处理数据。" + } +} diff --git a/account/admin/skills/system/run-skill-script/SKILL.md b/account/admin/skills/system/run-skill-script/SKILL.md new file mode 100644 index 0000000..baa03ff --- /dev/null +++ b/account/admin/skills/system/run-skill-script/SKILL.md @@ -0,0 +1,30 @@ +--- +name: run-skill-script +description: Execute a skill's script file with arguments. When you need to run skill functionality, execute specific operations, or process data with skill. +system: true +handler: skills +tool-name: run_skill_script +category: Skills Management +--- + +# Run Skill Script + +运行技能的脚本。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| skill_name | string | 是 | 技能名称 | +| script_name | string | 是 | 脚本文件名(如 get_time.py) | +| args | array | 否 | 命令行参数 | + +## Workflow + +1. 先用 `get_skill_info` 了解可用脚本 +2. 指定脚本名称和参数执行 + +## Related Skills + +- `get-skill-info`: 查看可用脚本 +- `list-skills`: 列出所有技能 diff --git a/account/admin/skills/system/schedule-task/.openakita-i18n.json b/account/admin/skills/system/schedule-task/.openakita-i18n.json new file mode 100644 index 0000000..45509ce --- /dev/null +++ b/account/admin/skills/system/schedule-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "创建定时任务", + "description": "创建定时任务或提醒,必须实际调用此工具才能创建任务。" + } +} diff --git a/account/admin/skills/system/schedule-task/SKILL.md b/account/admin/skills/system/schedule-task/SKILL.md new file mode 100644 index 0000000..42a35cd --- /dev/null +++ b/account/admin/skills/system/schedule-task/SKILL.md @@ -0,0 +1,89 @@ +--- +name: schedule-task +description: Create scheduled task or reminder. IMPORTANT - must actually call this tool to create task. Just saying 'OK I will remind you' does NOT create the task. Task types - (1) reminder for simple messages, (2) task for AI operations. +system: true +handler: scheduled +tool-name: schedule_task +category: Scheduled Tasks +--- + +# Schedule Task + +创建定时任务或提醒。 + +## Important + +**必须调用此工具才能创建任务!只是说"好的我会提醒你"不会创建任务!** + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| name | string | 是 | 任务名称 | +| description | string | 是 | 任务描述 | +| task_type | string | 是 | 任务类型:reminder 或 task | +| trigger_type | string | 是 | 触发类型:once, interval, cron | +| trigger_config | object | 是 | 触发配置(见下方) | +| reminder_message | string | 否 | 提醒消息(仅 reminder 类型) | +| prompt | string | 否 | AI 执行提示(仅 task 类型) | + +## Task Type Guidelines + +**90% 的提醒都应该是 reminder 类型!** + +✅ **reminder**(默认优先): +- "提醒我喝水" → reminder +- "站立提醒" → reminder +- "叫我起床" → reminder + +❌ **task**(仅当需要 AI 执行操作时): +- "查询天气告诉我" → task(需要查询) +- "截图发给我" → task(需要操作) + +## Trigger Config + +**once(一次性)**: +```json +{"run_at": "2026-02-01 10:00"} +``` + +**interval(间隔执行)**: +```json +{"interval_minutes": 30} +``` + +**cron(cron 表达式)**: +```json +{"cron": "0 9 * * *"} +``` + +## Examples + +**每小时喝水提醒**: +```json +{ + "name": "喝水提醒", + "description": "每小时提醒喝水", + "task_type": "reminder", + "trigger_type": "interval", + "trigger_config": {"interval_minutes": 60}, + "reminder_message": "该喝水了!" +} +``` + +**每天早上查天气**: +```json +{ + "name": "天气播报", + "description": "每天早上9点查询天气", + "task_type": "task", + "trigger_type": "cron", + "trigger_config": {"cron": "0 9 * * *"}, + "prompt": "查询今天的天气并告诉我" +} +``` + +## Related Skills + +- `list-scheduled-tasks`: 查看已创建的任务 +- `cancel-scheduled-task`: 取消任务 diff --git a/account/admin/skills/system/search-hub-agents/SKILL.md b/account/admin/skills/system/search-hub-agents/SKILL.md new file mode 100644 index 0000000..1685203 --- /dev/null +++ b/account/admin/skills/system/search-hub-agents/SKILL.md @@ -0,0 +1,41 @@ +--- +name: search-hub-agents +description: Search for Agents on the OpenAkita Platform Agent Store +system: true +handler: agent_hub +tool-name: search_hub_agents +category: Platform +--- + +# search-hub-agents + +Search for Agents on the OpenAkita Platform Agent Store. + +## When to Use + +- User wants to find or browse Agents on the OpenAkita marketplace +- User asks "有什么 Agent 可以用" or "搜索一个 XX Agent" +- User wants to discover community-shared Agents by category + +## Workflow + +1. Call `search_hub_agents` with optional filters +2. Review results — note the `id` field for each Agent +3. Use `get_hub_agent_detail` (from install-hub-agent) to inspect before installing +4. Use `install_hub_agent` to install the chosen Agent + +## Parameters + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `query` | No | Search keyword (e.g. "客服", "project manager") | +| `category` | No | Filter: customer_service, development, business, creative, education, productivity, general | +| `sort` | No | Sort by: downloads (default), rating, newest | +| `page` | No | Page number (default 1, 20 results per page) | + +## Fallback + +If the remote Agent Store is unavailable: +- Local Agent import/export via `.akita-agent` files still works +- Use `list_exportable_agents` to see local Agents +- Suggest user retry later or check network diff --git a/account/admin/skills/system/search-memory/.openakita-i18n.json b/account/admin/skills/system/search-memory/.openakita-i18n.json new file mode 100644 index 0000000..34dd595 --- /dev/null +++ b/account/admin/skills/system/search-memory/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "搜索记忆", + "description": "按关键词搜索相关记忆,回忆过往信息、查找用户偏好或检查已学习的模式。" + } +} diff --git a/account/admin/skills/system/search-memory/SKILL.md b/account/admin/skills/system/search-memory/SKILL.md new file mode 100644 index 0000000..07ef70f --- /dev/null +++ b/account/admin/skills/system/search-memory/SKILL.md @@ -0,0 +1,44 @@ +--- +name: search-memory +description: Search relevant memories by keyword and optional type filter. When you need to recall past information, find user preferences, or check learned patterns. +system: true +handler: memory +tool-name: search_memory +category: Memory +--- + +# Search Memory + +搜索相关记忆。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| query | string | 是 | 搜索关键词 | +| type | string | 否 | 记忆类型过滤(可选) | + +## Memory Types for Filter + +- `fact`: 事实信息 +- `preference`: 用户偏好 +- `skill`: 技能知识 +- `error`: 错误教训 +- `rule`: 规则约定 + +## Examples + +**搜索用户偏好**: +```json +{"query": "代码风格", "type": "preference"} +``` + +**通用搜索**: +```json +{"query": "Python"} +``` + +## Related Skills + +- `add-memory`: 添加新记忆 +- `get-memory-stats`: 查看记忆统计 diff --git a/account/admin/skills/system/search-store-skills/SKILL.md b/account/admin/skills/system/search-store-skills/SKILL.md new file mode 100644 index 0000000..4557d3c --- /dev/null +++ b/account/admin/skills/system/search-store-skills/SKILL.md @@ -0,0 +1,48 @@ +--- +name: search-store-skills +description: Search for Skills on the OpenAkita Platform Skill Store +system: true +handler: skill_store +tool-name: search_store_skills +category: Platform +--- + +# search-store-skills + +Search for Skills on the OpenAkita Platform Skill Store. + +## When to Use + +- User wants to find or browse Skills on the OpenAkita marketplace +- User asks "有什么技能可以安装" or "搜索一个 XX Skill" +- User wants to discover Skills by trust level (official / certified / community) + +## Workflow + +1. Call `search_store_skills` with optional filters +2. Review results — note the `id` and `trustLevel` for each Skill +3. Use `get_store_skill_detail` to inspect before installing +4. Use `install_store_skill` to install the chosen Skill + +## Parameters + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `query` | No | Search keyword | +| `category` | No | Filter by category | +| `trust_level` | No | Filter: official, certified, community | +| `sort` | No | Sort by: installs (default), rating, newest, stars | +| `page` | No | Page number (default 1) | + +## Trust Levels + +- **official**: Maintained by the OpenAkita team +- **certified**: Reviewed and approved by the team +- **community**: Community-contributed, use at your own discretion + +## Fallback + +If the remote Skill Store is unavailable: +- Local skill management still works +- Skills can be installed from GitHub using `install_skill` +- The skills.sh marketplace can be accessed via Setup Center diff --git a/account/admin/skills/system/send-sticker/.openakita-i18n.json b/account/admin/skills/system/send-sticker/.openakita-i18n.json new file mode 100644 index 0000000..65a0469 --- /dev/null +++ b/account/admin/skills/system/send-sticker/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "发送表情包", + "description": "搜索并发送表情包图片,在闲聊、问候、鼓励等场景下让对话更生动有趣。" + } +} diff --git a/account/admin/skills/system/send-sticker/SKILL.md b/account/admin/skills/system/send-sticker/SKILL.md new file mode 100644 index 0000000..6a574f0 --- /dev/null +++ b/account/admin/skills/system/send-sticker/SKILL.md @@ -0,0 +1,70 @@ +--- +name: send-sticker +description: 搜索并发送表情包图片。在闲聊、问候、鼓励等场景下使用,让对话更生动有趣。 +system: true +handler: sticker +tool-name: send_sticker +category: Communication +--- + +# 发送表情包 + +## 何时使用 + +- 闲聊问候时,增加互动趣味 +- 鼓励用户完成任务时 +- 表达情绪(开心/难过/惊讶等) +- 早安/晚安问候时(配合活人感模式) +- 庆祝任务成功完成 + +## 何时不使用 + +- 商务角色(sticker_preference=never) +- 用户明确表示不喜欢表情包 +- 正式的技术讨论中 +- 用户情绪不好需要安慰时(文字更合适) + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| query | string | 否 | 搜索关键词(如:鼓掌/开心/加油) | +| mood | string | 否 | 情绪类型,与 query 二选一 | +| category | string | 否 | 限定分类(如:猫/程序员) | + +## mood 类型 + +- `happy` - 开心、高兴 +- `sad` - 难过、伤心 +- `angry` - 生气 +- `greeting` - 问候(早安、晚安) +- `encourage` - 加油、鼓励 +- `love` - 爱心、比心 +- `tired` - 累了、摸鱼 +- `surprise` - 震惊、惊讶 + +## 角色配合 + +| 角色 | 频率 | 偏好 | +|------|------|------| +| 默认 | 偶尔 | 通用 | +| 商务 | 不使用 | - | +| 技术 | 偶尔 | 程序员 | +| 女友 | 频繁 | 可爱/心心 | +| 男友 | 适中 | 搞笑 | +| 家人 | 适中 | 通用 | +| 管家 | 偶尔 | 通用 | +| 贾维斯 | 适中 | 滑稽/程序员 | + +## 示例 + +``` +# 按情绪发送 +send_sticker(mood="happy") + +# 按关键词搜索 +send_sticker(query="加油") + +# 限定分类 +send_sticker(query="笑", category="猫") +``` diff --git a/account/admin/skills/system/set-task-timeout/.openakita-i18n.json b/account/admin/skills/system/set-task-timeout/.openakita-i18n.json new file mode 100644 index 0000000..bcb79ae --- /dev/null +++ b/account/admin/skills/system/set-task-timeout/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "设置任务超时", + "description": "调整当前任务的超时策略,适用于预期耗时较长的任务。" + } +} diff --git a/account/admin/skills/system/set-task-timeout/SKILL.md b/account/admin/skills/system/set-task-timeout/SKILL.md new file mode 100644 index 0000000..a66f6b1 --- /dev/null +++ b/account/admin/skills/system/set-task-timeout/SKILL.md @@ -0,0 +1,44 @@ +--- +name: set-task-timeout +description: Adjust current task timeout policy. Use when the task is expected to take long, or when the system is too aggressive switching models. Prefer increasing timeout for long-running tasks with steady progress. +system: true +handler: system +tool-name: set_task_timeout +category: System +--- + +# Set Task Timeout + +动态调整当前任务的超时策略,主要用于避免"卡死检测"误触发。 + +## When to Use + +- 长任务开始前,预防超时警告 +- 发现任务被频繁触发超时警告时 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| progress_timeout_seconds | integer | 是 | 无进展超时阈值(秒),建议 600~3600 | +| hard_timeout_seconds | integer | 否 | 硬超时上限(秒,0=禁用) | +| reason | string | 是 | 简要说明调整原因 | + +## Examples + +**长时间浏览器任务**: +```json +{ + "progress_timeout_seconds": 1800, + "reason": "需要完成多步浏览器操作,预计耗时较长" +} +``` + +## Note + +该设置只影响当前会话正在执行的任务,不影响全局配置。 + +## Related Skills + +- `create-plan`: 创建任务计划 +- `enable-thinking`: 启用深度思考 diff --git a/account/admin/skills/system/skip-profile-question/.openakita-i18n.json b/account/admin/skills/system/skip-profile-question/.openakita-i18n.json new file mode 100644 index 0000000..c3a2fdc --- /dev/null +++ b/account/admin/skills/system/skip-profile-question/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "跳过画像问题", + "description": "当用户明确拒绝回答画像问题时,跳过当前问题。" + } +} diff --git a/account/admin/skills/system/skip-profile-question/SKILL.md b/account/admin/skills/system/skip-profile-question/SKILL.md new file mode 100644 index 0000000..865b655 --- /dev/null +++ b/account/admin/skills/system/skip-profile-question/SKILL.md @@ -0,0 +1,29 @@ +--- +name: skip-profile-question +description: Skip profile question when user explicitly refuses to answer. When user says 'I don't want to answer' or 'skip this question', use this tool to stop asking about that item. +system: true +handler: profile +tool-name: skip_profile_question +category: User Profile +--- + +# Skip Profile Question + +跳过档案问题(以后不再询问)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| key | string | 是 | 要跳过的档案项键名 | + +## When to Use + +- 用户说"不想回答" +- 用户说"跳过这个问题" +- 用户表示不愿透露某信息 + +## Related Skills + +- `update-user-profile`: 更新档案 +- `get-user-profile`: 获取档案 diff --git a/account/admin/skills/system/submit-skill-repo/SKILL.md b/account/admin/skills/system/submit-skill-repo/SKILL.md new file mode 100644 index 0000000..5d3d4d8 --- /dev/null +++ b/account/admin/skills/system/submit-skill-repo/SKILL.md @@ -0,0 +1,29 @@ +--- +name: submit-skill-repo +description: Submit a GitHub repository to be indexed by the OpenAkita Skill Store. Enables users to share and register community Skills on the platform. +version: 1.0.0 +--- + +# submit-skill-repo + +Submit a GitHub repository to be indexed by the OpenAkita Skill Store. + +## Tools + +- submit_skill_repo - Submit a GitHub repo URL for skill indexing + +## Usage + +Use this skill when the user wants to: +- Share their GitHub repository containing Skills +- Submit a community Skill to the platform +- Register a new Skill source for the Skill Store + +## Parameters + +- epo_url (required): GitHub repository URL (e.g. https://github.com/owner/repo) + +## Examples + +- "把我的 GitHub 仓库提交到 Skill Store" +- "提交 https://github.com/my-org/my-skill 到平台" \ No newline at end of file diff --git a/account/admin/skills/system/switch-persona/.openakita-i18n.json b/account/admin/skills/system/switch-persona/.openakita-i18n.json new file mode 100644 index 0000000..2bc996d --- /dev/null +++ b/account/admin/skills/system/switch-persona/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "切换人格", + "description": "切换 Agent 人格预设角色,支持默认助手、商务助理、技术专家等多种预设。" + } +} diff --git a/account/admin/skills/system/switch-persona/SKILL.md b/account/admin/skills/system/switch-persona/SKILL.md new file mode 100644 index 0000000..802379b --- /dev/null +++ b/account/admin/skills/system/switch-persona/SKILL.md @@ -0,0 +1,53 @@ +--- +name: switch-persona +description: 切换 Agent 人格预设角色。支持 8 种预设:默认助手、商务助理、技术专家、私人管家、女友感、男友感、家人感、贾维斯。 +system: true +handler: persona +tool-name: switch_persona +category: Persona +--- + +# 切换人格预设 + +## 何时使用 + +- 用户要求切换角色/性格 +- 用户说"正式一点"/"随意一点"/"温柔一点"等 +- 用户希望改变 Agent 的沟通风格 +- 首次使用时的角色选择引导 + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| preset_name | string | 是 | 预设名称 | + +## 可用预设 + +- `default` - 默认助手(专业友好) +- `business` - 商务助理(正式高效,不使用表情) +- `tech_expert` - 技术专家(严谨深度,偶尔技术梗) +- `butler` - 私人管家(周到体贴,主动提醒) +- `girlfriend` - 女友感(温柔关心,使用表情包) +- `boyfriend` - 男友感(阳光鼓励,幽默风趣) +- `family` - 家人感(亲切唠叨,关心健康) +- `jarvis` - 贾维斯(英式幽默、小叛逆、话唠,任务时严谨) + +## 示例 + +``` +用户: "你能像个女朋友一样跟我聊天吗" +→ switch_persona(preset_name="girlfriend") + +用户: "正式一点" +→ switch_persona(preset_name="business") + +用户: "随意点,像朋友一样" +→ switch_persona(preset_name="default") + update_persona_trait(dimension="formality", preference="casual") +``` + +## 注意事项 + +- 预设只是起点,用户的实际偏好会通过对话不断叠加调整 +- 切换后 Agent 应立即按新角色风格回复 +- 可以配合 `update_persona_trait` 微调具体维度 diff --git a/account/admin/skills/system/toggle-proactive/.openakita-i18n.json b/account/admin/skills/system/toggle-proactive/.openakita-i18n.json new file mode 100644 index 0000000..e3d5427 --- /dev/null +++ b/account/admin/skills/system/toggle-proactive/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "活人感模式", + "description": "开关活人感模式,开启后 Agent 会主动发送问候、任务提醒和关键回顾。" + } +} diff --git a/account/admin/skills/system/toggle-proactive/SKILL.md b/account/admin/skills/system/toggle-proactive/SKILL.md new file mode 100644 index 0000000..94e20de --- /dev/null +++ b/account/admin/skills/system/toggle-proactive/SKILL.md @@ -0,0 +1,53 @@ +--- +name: toggle-proactive +description: 开关活人感模式。开启后 Agent 会主动发送问候、任务提醒、关键回顾等消息。 +system: true +handler: persona +tool-name: toggle_proactive +category: Persona +--- + +# 活人感模式开关 + +## 何时使用 + +- 用户要求开启/关闭主动消息 +- 用户说"别主动给我发消息了" +- 用户说"你可以主动跟我聊天" +- 用户在首次人格引导中选择开启 + +## 参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| enabled | boolean | 是 | 是否启用 | + +## 功能说明 + +开启后 Agent 会通过 IM 通道主动发送: + +- **早安问候**: 每天早上(7-9 点) +- **任务跟进**: 提醒未完成的任务 +- **关键回顾**: 之前对话中的重要信息 +- **闲聊问候**: 长时间未互动时 +- **晚安提醒**: 晚上(仅亲近角色) + +## 频率控制 + +- 每日最多 3 条(自适应调整) +- 两条之间至少间隔 2 小时 +- 安静时段(23:00-07:00)不发送 +- 根据用户反馈自动调整频率 + +## 示例 + +``` +用户: "开启活人感模式" +→ toggle_proactive(enabled=true) + +用户: "别主动给我发消息了" +→ toggle_proactive(enabled=false) + +用户: "少发点消息" +→ update_persona_trait(dimension="proactiveness", preference="low") +``` diff --git a/account/admin/skills/system/trigger-scheduled-task/.openakita-i18n.json b/account/admin/skills/system/trigger-scheduled-task/.openakita-i18n.json new file mode 100644 index 0000000..0046031 --- /dev/null +++ b/account/admin/skills/system/trigger-scheduled-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "立即触发任务", + "description": "立即执行定时任务,无需等待预定时间,用于测试或提前运行。" + } +} diff --git a/account/admin/skills/system/trigger-scheduled-task/SKILL.md b/account/admin/skills/system/trigger-scheduled-task/SKILL.md new file mode 100644 index 0000000..4dcbaf9 --- /dev/null +++ b/account/admin/skills/system/trigger-scheduled-task/SKILL.md @@ -0,0 +1,28 @@ +--- +name: trigger-scheduled-task +description: Immediately trigger scheduled task without waiting for scheduled time. When you need to test task execution or run task ahead of schedule. +system: true +handler: scheduled +tool-name: trigger_scheduled_task +category: Scheduled Tasks +--- + +# Trigger Scheduled Task + +立即触发定时任务(不等待计划时间)。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| task_id | string | 是 | 任务 ID | + +## Notes + +- 不会影响原有的执行计划 +- 适用于测试任务或提前运行 + +## Related Skills + +- `list-scheduled-tasks`: 获取任务 ID +- `schedule-task`: 创建新任务 diff --git a/account/admin/skills/system/update-plan-step/.openakita-i18n.json b/account/admin/skills/system/update-plan-step/.openakita-i18n.json new file mode 100644 index 0000000..4fe2a17 --- /dev/null +++ b/account/admin/skills/system/update-plan-step/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "更新计划步骤", + "description": "更新计划中某个步骤的状态,每完成一步后必须调用以跟踪进度。" + } +} diff --git a/account/admin/skills/system/update-plan-step/SKILL.md b/account/admin/skills/system/update-plan-step/SKILL.md new file mode 100644 index 0000000..8127906 --- /dev/null +++ b/account/admin/skills/system/update-plan-step/SKILL.md @@ -0,0 +1,46 @@ +--- +name: update-plan-step +description: Update the status of a plan step. MUST call after completing each step to track progress. Status values - pending, in_progress, completed, failed, skipped. +system: true +handler: plan +tool-name: update_plan_step +category: Plan +--- + +# Update Plan Step + +更新计划中某个步骤的状态。每完成一步必须调用。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| step_id | string | 是 | 步骤 ID | +| status | string | 是 | pending / in_progress / completed / failed / skipped | +| result | string | 否 | 执行结果或错误信息 | + +## Examples + +**步骤完成**: +```json +{ + "step_id": "step_1", + "status": "completed", + "result": "已打开百度首页" +} +``` + +**步骤失败**: +```json +{ + "step_id": "step_2", + "status": "failed", + "result": "找不到搜索框元素" +} +``` + +## Related Skills + +- `create-plan`: 创建计划 +- `get-plan-status`: 查看计划状态 +- `complete-plan`: 完成计划 diff --git a/account/admin/skills/system/update-scheduled-task/.openakita-i18n.json b/account/admin/skills/system/update-scheduled-task/.openakita-i18n.json new file mode 100644 index 0000000..863d9de --- /dev/null +++ b/account/admin/skills/system/update-scheduled-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "更新定时任务", + "description": "修改定时任务设置(不删除),可修改通知开关和启用状态。" + } +} diff --git a/account/admin/skills/system/update-scheduled-task/SKILL.md b/account/admin/skills/system/update-scheduled-task/SKILL.md new file mode 100644 index 0000000..21d041a --- /dev/null +++ b/account/admin/skills/system/update-scheduled-task/SKILL.md @@ -0,0 +1,32 @@ +--- +name: update-scheduled-task +description: Modify scheduled task settings WITHOUT deleting. Can modify notify_on_start, notify_on_complete, enabled. Common uses - (1) 'Turn off notification' = notify=false, (2) 'Pause task' = enabled=false, (3) 'Resume task' = enabled=true. +system: true +handler: scheduled +tool-name: update_scheduled_task +category: Scheduled Tasks +--- + +# Update Scheduled Task + +修改定时任务设置【不删除任务】。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| task_id | string | 是 | 要修改的任务 ID | +| notify_on_start | boolean | 否 | 开始时是否通知,不传=不修改 | +| notify_on_complete | boolean | 否 | 完成时是否通知,不传=不修改 | +| enabled | boolean | 否 | 启用/暂停任务,不传=不修改 | + +## Common Uses + +- "关闭提醒" → notify_on_start=false, notify_on_complete=false +- "暂停任务" → enabled=false +- "恢复任务" → enabled=true + +## Related Skills + +- `list-scheduled-tasks`: 获取任务 ID +- `cancel-scheduled-task`: 永久删除任务 diff --git a/account/admin/skills/system/update-user-profile/.openakita-i18n.json b/account/admin/skills/system/update-user-profile/.openakita-i18n.json new file mode 100644 index 0000000..6cf9bf9 --- /dev/null +++ b/account/admin/skills/system/update-user-profile/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "更新用户画像", + "description": "当用户分享偏好、习惯或工作信息时,更新用户画像。" + } +} diff --git a/account/admin/skills/system/update-user-profile/SKILL.md b/account/admin/skills/system/update-user-profile/SKILL.md new file mode 100644 index 0000000..9aaecae --- /dev/null +++ b/account/admin/skills/system/update-user-profile/SKILL.md @@ -0,0 +1,38 @@ +--- +name: update-user-profile +description: Update user profile information when user shares preferences, habits, or work details. When you need to save user preferences, remember user's work domain, or provide personalized service. +system: true +handler: profile +tool-name: update_user_profile +category: User Profile +--- + +# Update User Profile + +更新用户档案信息。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| key | string | 是 | 档案项键名 | +| value | string | 是 | 用户提供的信息值 | + +## Supported Keys + +- name: 称呼 +- agent_role: Agent 角色 +- work_field: 工作领域 +- preferred_language: 编程语言偏好 +- os: 操作系统 +- ide: 开发工具 +- detail_level: 详细程度偏好 +- code_comment_lang: 代码注释语言 +- work_hours: 工作时间 +- timezone: 时区 +- confirm_preference: 确认偏好 + +## Related Skills + +- `get-user-profile`: 获取档案 +- `skip-profile-question`: 跳过问题 diff --git a/account/admin/skills/system/web-search/.openakita-i18n.json b/account/admin/skills/system/web-search/.openakita-i18n.json new file mode 100644 index 0000000..50ff35d --- /dev/null +++ b/account/admin/skills/system/web-search/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "网页搜索", + "description": "使用 DuckDuckGo 搜索网页,查找最新信息、验证事实或查阅文档。" + } +} diff --git a/account/admin/skills/system/web-search/SKILL.md b/account/admin/skills/system/web-search/SKILL.md new file mode 100644 index 0000000..335cd57 --- /dev/null +++ b/account/admin/skills/system/web-search/SKILL.md @@ -0,0 +1,37 @@ +--- +name: web-search +description: Search the web using DuckDuckGo. Use when you need to find current information, verify facts, look up documentation, or answer questions requiring up-to-date knowledge. Returns titles, URLs, and snippets. +system: true +handler: web_search +tool-name: web_search +category: Web Search +--- + +# Web Search + +使用 DuckDuckGo 搜索网页,获取最新信息。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| query | string | 是 | 搜索关键词 | +| max_results | integer | 否 | 最大结果数(1-20,默认 5) | +| region | string | 否 | 地区代码(wt-wt 全球,cn-zh 中国) | +| safesearch | string | 否 | 安全搜索(on/moderate/off) | + +## Examples + +**搜索信息**: +```json +{"query": "Python asyncio 教程", "max_results": 5} +``` + +**搜索中文内容**: +```json +{"query": "天气预报", "region": "cn-zh"} +``` + +## Related Skills + +- `news-search`: 搜索新闻 diff --git a/account/admin/skills/system/write-file/.openakita-i18n.json b/account/admin/skills/system/write-file/.openakita-i18n.json new file mode 100644 index 0000000..09963c3 --- /dev/null +++ b/account/admin/skills/system/write-file/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "写入文件", + "description": "将内容写入文件,创建新文件或覆盖已有文件。" + } +} diff --git a/account/admin/skills/system/write-file/SKILL.md b/account/admin/skills/system/write-file/SKILL.md new file mode 100644 index 0000000..be07de8 --- /dev/null +++ b/account/admin/skills/system/write-file/SKILL.md @@ -0,0 +1,48 @@ +--- +name: write-file +description: Write content to file, creating new or overwriting existing. When you need to create new files, update file content, or save generated code/data. +system: true +handler: filesystem +tool-name: write_file +category: File System +--- + +# Write File + +写入文件内容。 + +## Parameters + +| 参数 | 类型 | 必填 | 说明 | +|-----|------|-----|------| +| path | string | 是 | 文件路径 | +| content | string | 是 | 文件内容 | + +## Examples + +**创建配置文件**: +```json +{ + "path": "config.json", + "content": "{\"debug\": true}" +} +``` + +**写入代码文件**: +```json +{ + "path": "hello.py", + "content": "print('Hello, World!')" +} +``` + +## Notes + +- 会覆盖已存在的文件 +- 自动创建父目录(如果不存在) +- 使用 UTF-8 编码 + +## Related Skills + +- `read-file`: 读取文件 +- `run-shell`: 执行脚本 diff --git a/account/admin/skills/theme-factory/LICENSE.txt b/account/admin/skills/theme-factory/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/theme-factory/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/theme-factory/SKILL.md b/account/admin/skills/theme-factory/SKILL.md new file mode 100644 index 0000000..82f3291 --- /dev/null +++ b/account/admin/skills/theme-factory/SKILL.md @@ -0,0 +1,59 @@ +--- +name: openakita/skills@theme-factory +description: Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly. +license: Complete terms in LICENSE.txt +--- + + +# Theme Factory Skill + +This skill provides a curated collection of professional font and color themes themes, each with carefully selected color palettes and font pairings. Once a theme is chosen, it can be applied to any artifact. + +## Purpose + +To apply consistent, professional styling to presentation slide decks, use this skill. Each theme includes: +- A cohesive color palette with hex codes +- Complementary font pairings for headers and body text +- A distinct visual identity suitable for different contexts and audiences + +## Usage Instructions + +To apply styling to a slide deck or other artifact: + +1. **Show the theme showcase**: Display the `theme-showcase.pdf` file to allow users to see all available themes visually. Do not make any modifications to it; simply show the file for viewing. +2. **Ask for their choice**: Ask which theme to apply to the deck +3. **Wait for selection**: Get explicit confirmation about the chosen theme +4. **Apply the theme**: Once a theme has been chosen, apply the selected theme's colors and fonts to the deck/artifact + +## Themes Available + +The following 10 themes are available, each showcased in `theme-showcase.pdf`: + +1. **Ocean Depths** - Professional and calming maritime theme +2. **Sunset Boulevard** - Warm and vibrant sunset colors +3. **Forest Canopy** - Natural and grounded earth tones +4. **Modern Minimalist** - Clean and contemporary grayscale +5. **Golden Hour** - Rich and warm autumnal palette +6. **Arctic Frost** - Cool and crisp winter-inspired theme +7. **Desert Rose** - Soft and sophisticated dusty tones +8. **Tech Innovation** - Bold and modern tech aesthetic +9. **Botanical Garden** - Fresh and organic garden colors +10. **Midnight Galaxy** - Dramatic and cosmic deep tones + +## Theme Details + +Each theme is defined in the `themes/` directory with complete specifications including: +- Cohesive color palette with hex codes +- Complementary font pairings for headers and body text +- Distinct visual identity suitable for different contexts and audiences + +## Application Process + +After a preferred theme is selected: +1. Read the corresponding theme file from the `themes/` directory +2. Apply the specified colors and fonts consistently throughout the deck +3. Ensure proper contrast and readability +4. Maintain the theme's visual identity across all slides + +## Create your Own Theme +To handle cases where none of the existing themes work for an artifact, create a custom theme. Based on provided inputs, generate a new theme similar to the ones above. Give the theme a similar name describing what the font/color combinations represent. Use any basic description provided to choose appropriate colors/fonts. After generating the theme, show it for review and verification. Following that, apply the theme as described above. diff --git a/account/admin/skills/theme-factory/theme-showcase.pdf b/account/admin/skills/theme-factory/theme-showcase.pdf new file mode 100644 index 0000000..24495d1 Binary files /dev/null and b/account/admin/skills/theme-factory/theme-showcase.pdf differ diff --git a/account/admin/skills/theme-factory/themes/arctic-frost.md b/account/admin/skills/theme-factory/themes/arctic-frost.md new file mode 100644 index 0000000..e9f1eb0 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/arctic-frost.md @@ -0,0 +1,19 @@ +# Arctic Frost + +A cool and crisp winter-inspired theme that conveys clarity, precision, and professionalism. + +## Color Palette + +- **Ice Blue**: `#d4e4f7` - Light backgrounds and highlights +- **Steel Blue**: `#4a6fa5` - Primary accent color +- **Silver**: `#c0c0c0` - Metallic accent elements +- **Crisp White**: `#fafafa` - Clean backgrounds and text + +## Typography + +- **Headers**: DejaVu Sans Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Healthcare presentations, technology solutions, winter sports, clean tech, pharmaceutical content. diff --git a/account/admin/skills/theme-factory/themes/botanical-garden.md b/account/admin/skills/theme-factory/themes/botanical-garden.md new file mode 100644 index 0000000..0c95bf7 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/botanical-garden.md @@ -0,0 +1,19 @@ +# Botanical Garden + +A fresh and organic theme featuring vibrant garden-inspired colors for lively presentations. + +## Color Palette + +- **Fern Green**: `#4a7c59` - Rich natural green +- **Marigold**: `#f9a620` - Bright floral accent +- **Terracotta**: `#b7472a` - Earthy warm tone +- **Cream**: `#f5f3ed` - Soft neutral backgrounds + +## Typography + +- **Headers**: DejaVu Serif Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Garden centers, food presentations, farm-to-table content, botanical brands, natural products. diff --git a/account/admin/skills/theme-factory/themes/desert-rose.md b/account/admin/skills/theme-factory/themes/desert-rose.md new file mode 100644 index 0000000..ea7c74e --- /dev/null +++ b/account/admin/skills/theme-factory/themes/desert-rose.md @@ -0,0 +1,19 @@ +# Desert Rose + +A soft and sophisticated theme with dusty, muted tones perfect for elegant presentations. + +## Color Palette + +- **Dusty Rose**: `#d4a5a5` - Soft primary color +- **Clay**: `#b87d6d` - Earthy accent +- **Sand**: `#e8d5c4` - Warm neutral backgrounds +- **Deep Burgundy**: `#5d2e46` - Rich dark contrast + +## Typography + +- **Headers**: FreeSans Bold +- **Body Text**: FreeSans + +## Best Used For + +Fashion presentations, beauty brands, wedding planning, interior design, boutique businesses. diff --git a/account/admin/skills/theme-factory/themes/forest-canopy.md b/account/admin/skills/theme-factory/themes/forest-canopy.md new file mode 100644 index 0000000..90c2b26 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/forest-canopy.md @@ -0,0 +1,19 @@ +# Forest Canopy + +A natural and grounded theme featuring earth tones inspired by dense forest environments. + +## Color Palette + +- **Forest Green**: `#2d4a2b` - Primary dark green +- **Sage**: `#7d8471` - Muted green accent +- **Olive**: `#a4ac86` - Light accent color +- **Ivory**: `#faf9f6` - Backgrounds and text + +## Typography + +- **Headers**: FreeSerif Bold +- **Body Text**: FreeSans + +## Best Used For + +Environmental presentations, sustainability reports, outdoor brands, wellness content, organic products. diff --git a/account/admin/skills/theme-factory/themes/golden-hour.md b/account/admin/skills/theme-factory/themes/golden-hour.md new file mode 100644 index 0000000..ed8fc25 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/golden-hour.md @@ -0,0 +1,19 @@ +# Golden Hour + +A rich and warm autumnal palette that creates an inviting and sophisticated atmosphere. + +## Color Palette + +- **Mustard Yellow**: `#f4a900` - Bold primary accent +- **Terracotta**: `#c1666b` - Warm secondary color +- **Warm Beige**: `#d4b896` - Neutral backgrounds +- **Chocolate Brown**: `#4a403a` - Dark text and anchors + +## Typography + +- **Headers**: FreeSans Bold +- **Body Text**: FreeSans + +## Best Used For + +Restaurant presentations, hospitality brands, fall campaigns, cozy lifestyle content, artisan products. diff --git a/account/admin/skills/theme-factory/themes/midnight-galaxy.md b/account/admin/skills/theme-factory/themes/midnight-galaxy.md new file mode 100644 index 0000000..97e1c5f --- /dev/null +++ b/account/admin/skills/theme-factory/themes/midnight-galaxy.md @@ -0,0 +1,19 @@ +# Midnight Galaxy + +A dramatic and cosmic theme with deep purples and mystical tones for impactful presentations. + +## Color Palette + +- **Deep Purple**: `#2b1e3e` - Rich dark base +- **Cosmic Blue**: `#4a4e8f` - Mystical mid-tone +- **Lavender**: `#a490c2` - Soft accent color +- **Silver**: `#e6e6fa` - Light highlights and text + +## Typography + +- **Headers**: FreeSans Bold +- **Body Text**: FreeSans + +## Best Used For + +Entertainment industry, gaming presentations, nightlife venues, luxury brands, creative agencies. diff --git a/account/admin/skills/theme-factory/themes/modern-minimalist.md b/account/admin/skills/theme-factory/themes/modern-minimalist.md new file mode 100644 index 0000000..6bd26a2 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/modern-minimalist.md @@ -0,0 +1,19 @@ +# Modern Minimalist + +A clean and contemporary theme with a sophisticated grayscale palette for maximum versatility. + +## Color Palette + +- **Charcoal**: `#36454f` - Primary dark color +- **Slate Gray**: `#708090` - Medium gray for accents +- **Light Gray**: `#d3d3d3` - Backgrounds and dividers +- **White**: `#ffffff` - Text and clean backgrounds + +## Typography + +- **Headers**: DejaVu Sans Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Tech presentations, architecture portfolios, design showcases, modern business proposals, data visualization. diff --git a/account/admin/skills/theme-factory/themes/ocean-depths.md b/account/admin/skills/theme-factory/themes/ocean-depths.md new file mode 100644 index 0000000..b675126 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/ocean-depths.md @@ -0,0 +1,19 @@ +# Ocean Depths + +A professional and calming maritime theme that evokes the serenity of deep ocean waters. + +## Color Palette + +- **Deep Navy**: `#1a2332` - Primary background color +- **Teal**: `#2d8b8b` - Accent color for highlights and emphasis +- **Seafoam**: `#a8dadc` - Secondary accent for lighter elements +- **Cream**: `#f1faee` - Text and light backgrounds + +## Typography + +- **Headers**: DejaVu Sans Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Corporate presentations, financial reports, professional consulting decks, trust-building content. diff --git a/account/admin/skills/theme-factory/themes/sunset-boulevard.md b/account/admin/skills/theme-factory/themes/sunset-boulevard.md new file mode 100644 index 0000000..df799a0 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/sunset-boulevard.md @@ -0,0 +1,19 @@ +# Sunset Boulevard + +A warm and vibrant theme inspired by golden hour sunsets, perfect for energetic and creative presentations. + +## Color Palette + +- **Burnt Orange**: `#e76f51` - Primary accent color +- **Coral**: `#f4a261` - Secondary warm accent +- **Warm Sand**: `#e9c46a` - Highlighting and backgrounds +- **Deep Purple**: `#264653` - Dark contrast and text + +## Typography + +- **Headers**: DejaVu Serif Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Creative pitches, marketing presentations, lifestyle brands, event promotions, inspirational content. diff --git a/account/admin/skills/theme-factory/themes/tech-innovation.md b/account/admin/skills/theme-factory/themes/tech-innovation.md new file mode 100644 index 0000000..e029a43 --- /dev/null +++ b/account/admin/skills/theme-factory/themes/tech-innovation.md @@ -0,0 +1,19 @@ +# Tech Innovation + +A bold and modern theme with high-contrast colors perfect for cutting-edge technology presentations. + +## Color Palette + +- **Electric Blue**: `#0066ff` - Vibrant primary accent +- **Neon Cyan**: `#00ffff` - Bright highlight color +- **Dark Gray**: `#1e1e1e` - Deep backgrounds +- **White**: `#ffffff` - Clean text and contrast + +## Typography + +- **Headers**: DejaVu Sans Bold +- **Body Text**: DejaVu Sans + +## Best Used For + +Tech startups, software launches, innovation showcases, AI/ML presentations, digital transformation content. diff --git a/account/admin/skills/todoist-task/.openakita-i18n.json b/account/admin/skills/todoist-task/.openakita-i18n.json new file mode 100644 index 0000000..36d8bf9 --- /dev/null +++ b/account/admin/skills/todoist-task/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "Todoist 任务管理", + "description": "通过 Todoist REST API v2 管理任务、项目、标签和过滤器,支持任务 CRUD、优先级、截止日期、重复任务和批量操作。" + } +} diff --git a/account/admin/skills/todoist-task/SKILL.md b/account/admin/skills/todoist-task/SKILL.md new file mode 100644 index 0000000..56f6703 --- /dev/null +++ b/account/admin/skills/todoist-task/SKILL.md @@ -0,0 +1,639 @@ +--- +name: openakita/skills@todoist-task +description: Manage Todoist tasks, projects, sections, labels, and filters via REST API v2. Supports task CRUD, due dates, priorities, recurring tasks, project organization, and advanced filtering. Based on doggy8088/agent-skills/todoist-api, using curl + jq. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Todoist Task — Todoist 任务管理 + +## When to Use + +- 用户需要创建、查看、更新或删除 Todoist 任务 +- 需要管理 Todoist 项目和分区 +- 需要设置任务优先级、截止日期、重复规则 +- 需要用标签分类任务 +- 需要查询和过滤任务 +- 需要将对话中讨论的待办事项同步到 Todoist +- 需要批量管理任务(导入/导出/整理) + +--- + +## Prerequisites + +### 必需配置 + +| 配置项 | 说明 | +|--------|------| +| `TODOIST_API_TOKEN` | Todoist API Token | + +**获取 Token:** + +1. 登录 Todoist → 设置 → 集成 → 开发者 +2. 或访问:https://app.todoist.com/app/settings/integrations/developer +3. 复制 API Token + +在 `.env` 中配置: + +``` +TODOIST_API_TOKEN=your_todoist_api_token_here +``` + +### 工具依赖 + +| 工具 | 用途 | 说明 | +|------|------|------| +| `curl` | HTTP API 调用 | 系统通常自带 | +| `jq` | JSON 解析 | Windows: `choco install jq`; macOS: `brew install jq` | + +### 验证配置 + +```bash +curl -s "https://api.todoist.com/rest/v2/projects" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.[0].name' +``` + +--- + +## Instructions + +### Todoist API v2 基础 + +所有请求发送到 `https://api.todoist.com/rest/v2/`,携带 Bearer Token: + +```bash +curl -s "https://api.todoist.com/rest/v2/{endpoint}" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" +``` + +### 核心概念 + +| 概念 | 说明 | +|------|------| +| Task(任务) | 待办事项,Todoist 的核心单元 | +| Project(项目) | 任务的容器,类似文件夹 | +| Section(分区) | 项目内的分组/栏目 | +| Label(标签) | 跨项目的任务分类标签 | +| Filter(过滤器) | 自定义查询条件 | +| Priority(优先级) | 1=普通, 2=低, 3=中, 4=紧急(API 与 UI 相反) | +| Due Date(截止日期) | 支持自然语言和 ISO 8601 | + +### 优先级映射 + +注意 API 的优先级数字与 Todoist UI 显示是**相反**的: + +| API 值 | UI 显示 | 颜色 | +|--------|---------|------| +| `priority: 1` | Priority 4(普通) | 无色 | +| `priority: 2` | Priority 3(低) | 蓝色 | +| `priority: 3` | Priority 2(中) | 橙色 | +| `priority: 4` | Priority 1(紧急) | 红色 | + +--- + +## Workflows + +### Workflow 1: 任务 CRUD + +#### 创建任务 + +**基本创建** + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "content": "完成项目方案", + "description": "包含技术选型和时间线", + "due_string": "明天下午3点", + "due_lang": "zh", + "priority": 4, + "project_id": "PROJECT_ID" + }' | jq '.' +``` + +**带标签和分区的创建** + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "content": "Review PR #42", + "description": "Check error handling and test coverage", + "due_date": "2025-03-05", + "priority": 3, + "project_id": "PROJECT_ID", + "section_id": "SECTION_ID", + "labels": ["code-review", "urgent"] + }' | jq '.' +``` + +**创建子任务** + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "content": "编写单元测试", + "parent_id": "PARENT_TASK_ID", + "priority": 2 + }' | jq '.' +``` + +#### 查看任务 + +**获取所有活跃任务** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +**按项目筛选** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks?project_id=PROJECT_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +**按标签筛选** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks?label=urgent" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +**使用过滤器查询** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks?filter=today%20%7C%20overdue" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +**获取单个任务** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks/TASK_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +#### 更新任务 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks/TASK_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "content": "更新后的任务标题", + "due_string": "下周一", + "due_lang": "zh", + "priority": 3 + }' | jq '.' +``` + +#### 完成任务 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks/TASK_ID/close" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" +``` + +#### 重新打开任务 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/tasks/TASK_ID/reopen" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" +``` + +#### 删除任务 + +```bash +curl -s -X DELETE "https://api.todoist.com/rest/v2/tasks/TASK_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" +``` + +--- + +### Workflow 2: 项目管理 + +#### 列出所有项目 + +```bash +curl -s "https://api.todoist.com/rest/v2/projects" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.[] | {id, name, color, is_favorite}' +``` + +#### 创建项目 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/projects" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Q2 产品开发", + "color": "blue", + "is_favorite": true, + "view_style": "board" + }' | jq '.' +``` + +`view_style` 可选: +- `list`:列表视图(默认) +- `board`:看板视图 + +#### 更新项目 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/projects/PROJECT_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Q2 产品开发(已完成)", + "color": "grey" + }' | jq '.' +``` + +#### 删除项目 + +```bash +curl -s -X DELETE "https://api.todoist.com/rest/v2/projects/PROJECT_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" +``` + +--- + +### Workflow 3: 分区管理 + +分区(Section)用于在项目内组织任务,类似看板的列。 + +#### 列出分区 + +```bash +curl -s "https://api.todoist.com/rest/v2/sections?project_id=PROJECT_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.' +``` + +#### 创建分区 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/sections" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "project_id": "PROJECT_ID", + "name": "进行中" + }' | jq '.' +``` + +#### 常见分区模板 + +**看板式** + +```bash +for section in "待处理" "进行中" "待审核" "已完成"; do + curl -s -X POST "https://api.todoist.com/rest/v2/sections" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"project_id\": \"PROJECT_ID\", \"name\": \"$section\"}" +done +``` + +**GTD 式** + +```bash +for section in "收集箱" "下一步行动" "等待中" "将来/也许" "参考资料"; do + curl -s -X POST "https://api.todoist.com/rest/v2/sections" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"project_id\": \"PROJECT_ID\", \"name\": \"$section\"}" +done +``` + +--- + +### Workflow 4: 标签管理 + +#### 列出所有标签 + +```bash +curl -s "https://api.todoist.com/rest/v2/labels" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq '.[] | {id, name, color, is_favorite}' +``` + +#### 创建标签 + +```bash +curl -s -X POST "https://api.todoist.com/rest/v2/labels" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "high-energy", + "color": "red" + }' | jq '.' +``` + +#### 推荐标签体系 + +| 类别 | 标签 | 用途 | +|------|------|------| +| 精力 | `high-energy`, `low-energy` | 按精力状态选择任务 | +| 时长 | `5min`, `15min`, `30min`, `1hour` | 按可用时间选择任务 | +| 场景 | `at-computer`, `at-phone`, `at-office`, `anywhere` | 按场景选择任务 | +| 类型 | `meeting`, `deep-work`, `admin`, `learning` | 按任务性质分类 | + +--- + +### Workflow 5: 截止日期与重复任务 + +#### 自然语言日期(推荐) + +Todoist 支持多语言自然语言日期: + +```json +{ + "due_string": "明天下午3点", + "due_lang": "zh" +} +``` + +| 中文表达 | 英文等效 | 解析结果 | +|---------|---------|---------| +| 今天 | today | 当天 | +| 明天 | tomorrow | 次日 | +| 后天 | in 2 days | 两天后 | +| 下周一 | next Monday | 下个周一 | +| 每天 | every day | 每日重复 | +| 每周一 | every Monday | 每周一重复 | +| 每月1号 | every 1st | 每月1日重复 | +| 3月15日 | March 15 | 指定日期 | + +#### ISO 日期格式 + +```json +{ + "due_date": "2025-03-15" +} +``` + +或带时间: + +```json +{ + "due_datetime": "2025-03-15T15:00:00Z" +} +``` + +#### 重复任务 + +```json +{ + "due_string": "every weekday at 9am", + "due_lang": "en" +} +``` + +常见重复规则: + +| 规则 | `due_string` | 说明 | +|------|-------------|------| +| 每日 | `every day` | 每天 | +| 工作日 | `every weekday` | 周一至周五 | +| 每周 | `every week` | 每 7 天 | +| 每月 | `every month` | 每月同日 | +| 每季度 | `every 3 months` | 每 3 个月 | +| 每年 | `every year` | 每年同日 | +| 完成后 3 天 | `every! 3 days` | 完成后 3 天再次出现 | +| 隔周一 | `every other Monday` | 每两周的周一 | + +--- + +### Workflow 6: 高级过滤查询 + +#### 过滤器语法 + +| 过滤器 | 说明 | +|--------|------| +| `today` | 今天到期的任务 | +| `overdue` | 已过期任务 | +| `today \| overdue` | 今天到期或已过期 | +| `7 days` | 未来 7 天到期 | +| `no date` | 没有截止日期的任务 | +| `p1` | 优先级 1(紧急) | +| `p1 & today` | 紧急且今天到期 | +| `#项目名` | 指定项目的任务 | +| `@标签名` | 指定标签的任务 | +| `assigned to: me` | 分配给自己的任务 | +| `created before: -7 days` | 7 天前创建的任务 | + +#### 查询示例 + +**今日待办** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks?filter=today%20%7C%20overdue" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq '.[] | {content, due: .due.string, priority}' +``` + +**本周紧急任务** + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks?filter=7%20days%20%26%20(p1%20%7C%20p2)" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq '.[] | {content, due: .due.string, priority}' +``` + +--- + +### Workflow 7: 批量操作 + +#### 从对话生成任务 + +当用户在对话中提到多个待办事项时,批量创建: + +```bash +tasks='[ + {"content": "准备周会PPT", "due_string": "明天", "priority": 3}, + {"content": "回复客户邮件", "due_string": "今天", "priority": 4}, + {"content": "代码审查 PR #55", "due_string": "后天", "priority": 2} +]' + +echo "$tasks" | jq -c '.[]' | while read task; do + curl -s -X POST "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$task" | jq '{id, content, url}' + sleep 0.3 +done +``` + +#### 批量完成任务 + +```bash +task_ids=("TASK_ID_1" "TASK_ID_2" "TASK_ID_3") + +for id in "${task_ids[@]}"; do + curl -s -X POST "https://api.todoist.com/rest/v2/tasks/$id/close" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" + sleep 0.3 +done +``` + +#### 任务导出 + +```bash +curl -s "https://api.todoist.com/rest/v2/tasks" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq -r '["内容","项目ID","优先级","截止日期","标签"], (.[] | [.content, .project_id, .priority, (.due.date // "无"), (.labels | join(","))]) | @csv' \ + > tasks_export.csv +``` + +--- + +## Output Format + +### 任务列表输出 + +``` +📋 今日待办 (5 项) + +🔴 [P1] 回复客户紧急邮件 + 📅 今天 14:00 | 🏷️ work, urgent + 📁 客户项目 + +🟠 [P2] Review PR #42 + 📅 今天 | 🏷️ code-review + 📁 开发任务 + +⚪ [P4] 整理会议纪要 + 📅 今天 | 🏷️ admin + 📁 日常事务 + +✅ 已完成: 3 项 | ⏰ 逾期: 1 项 +``` + +### 创建确认 + +``` +✅ 任务已创建 +- 内容: 完成项目方案 +- 项目: Q2 产品开发 +- 截止: 明天 15:00 +- 优先级: P1 (紧急) +- 标签: deep-work +- 链接: https://todoist.com/app/task/12345 +``` + +--- + +## Common Pitfalls + +### 1. API Token 无效 + +**症状**:所有请求返回 401 +**解决**:确认 `TODOIST_API_TOKEN` 正确设置,到 Todoist 设置页面重新获取 + +### 2. 优先级数字混淆 + +API 的 `priority: 4` 对应 UI 的 P1(紧急),这是反直觉的。牢记映射关系或在代码中使用常量: + +```bash +P1_URGENT=4 +P2_HIGH=3 +P3_MEDIUM=2 +P4_NORMAL=1 +``` + +### 3. 中文日期解析失败 + +使用中文自然语言日期时必须指定 `due_lang: "zh"`,否则会解析失败或解析为错误日期。 + +### 4. 过滤器 URL 编码 + +通过 curl 传递过滤器时需要 URL 编码: +- `|` → `%7C` +- `&` → `%26` +- `#` → `%23` +- 空格 → `%20` + +### 5. 项目/任务 ID 是字符串 + +Todoist REST API v2 返回的 ID 是字符串类型,不是数字。使用 jq 处理时注意类型。 + +### 6. 批量操作超频 + +Todoist API 的限制是每分钟约 450 次请求。批量操作时添加 sleep: + +```bash +sleep 0.3 # 每次请求间隔 300ms +``` + +### 7. 重复任务的 close vs delete + +- `close`(完成):对重复任务,会自动创建下一次任务 +- `delete`:永久删除,不会创建下次任务 + +确保对重复任务使用 `close` 而非 `delete`。 + +### 8. 时区问题 + +带时间的截止日期使用 UTC 格式。如果用户在东八区(CST),需注意时差: + +```json +{ + "due_datetime": "2025-03-15T07:00:00Z" +} +``` + +上述表示北京时间 15:00。 + +--- + +## 进阶用法 + +### 每日回顾脚本 + +```bash +echo "=== 📋 每日回顾 $(date +%Y-%m-%d) ===" +echo "" +echo "--- 🔴 逾期任务 ---" +curl -s "https://api.todoist.com/rest/v2/tasks?filter=overdue" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq -r '.[] | " ❗ \(.content) (原定: \(.due.date))"' +echo "" +echo "--- 📅 今日任务 ---" +curl -s "https://api.todoist.com/rest/v2/tasks?filter=today" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq -r '.[] | " • [\(if .priority == 4 then "P1" elif .priority == 3 then "P2" elif .priority == 2 then "P3" else "P4" end)] \(.content)"' +echo "" +echo "--- 📆 明日预览 ---" +curl -s "https://api.todoist.com/rest/v2/tasks?filter=tomorrow" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | \ + jq -r '.[] | " ○ \(.content)"' +``` + +### 项目进度统计 + +```bash +PROJECT_ID="your_project_id" +total=$(curl -s "https://api.todoist.com/rest/v2/tasks?project_id=$PROJECT_ID" \ + -H "Authorization: Bearer $TODOIST_API_TOKEN" | jq 'length') +echo "📊 项目进度: 剩余 $total 个活跃任务" +``` + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 默认项目 ID 和名称映射 +- 自定义标签体系 +- 任务模板(如每周例行任务) +- 与其他工具的集成配置 +- 团队成员 ID 映射 diff --git a/account/admin/skills/translate-pdf/.openakita-i18n.json b/account/admin/skills/translate-pdf/.openakita-i18n.json new file mode 100644 index 0000000..395319a --- /dev/null +++ b/account/admin/skills/translate-pdf/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "PDF 文档翻译", + "description": "翻译 PDF 文档并保留原始排版、表格、图片和格式,支持中英日韩等多语种及双语对照输出。" + } +} diff --git a/account/admin/skills/translate-pdf/SKILL.md b/account/admin/skills/translate-pdf/SKILL.md new file mode 100644 index 0000000..88b3c44 --- /dev/null +++ b/account/admin/skills/translate-pdf/SKILL.md @@ -0,0 +1,495 @@ +--- +name: openakita/skills@translate-pdf +description: Translate PDF documents while preserving original layout, styling, tables, images, and formatting. Supports Simplified Chinese, Traditional Chinese, English, Japanese, Korean, and more. Page-by-page translation with structure preservation. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Translate PDF — PDF 文档翻译 + +## When to Use + +- 用户需要将英文 PDF 翻译为中文(或其他语言) +- 需要保留 PDF 的原始排版、表格、图片和格式 +- 需要翻译学术论文、技术文档、商业报告 +- 需要双语对照的 PDF 输出 +- 需要批量翻译多个 PDF 文件 + +--- + +## Prerequisites + +### 必需依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| Python ≥ 3.10 | 运行翻译脚本 | 系统预装 | +| `PyMuPDF` (fitz) | PDF 解析与重建 | `pip install PyMuPDF` | +| `httpx` | HTTP API 调用 | `pip install httpx` | + +### 可选依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `pdf2image` | PDF 转图片(OCR 场景) | `pip install pdf2image` | +| `pytesseract` | OCR 文字识别 | `pip install pytesseract` | +| `pdfplumber` | 表格提取 | `pip install pdfplumber` | +| `reportlab` | PDF 生成 | `pip install reportlab` | +| `deep-translator` | 多引擎翻译 | `pip install deep-translator` | +| `openai` | GPT 翻译 | `pip install openai` | + +### 系统级依赖 + +| 工具 | 用途 | 说明 | +|------|------|------| +| Poppler | pdf2image 的后端 | Windows: 下载 poppler-utils; macOS: `brew install poppler` | +| Tesseract | OCR 引擎 | Windows: 下载安装包; macOS: `brew install tesseract` | +| 中文字体 | PDF 中文渲染 | 系统需安装中文字体(微软雅黑、思源黑体等) | + +### 验证安装 + +```bash +python -c "import fitz; print('PyMuPDF', fitz.version)" +python -c "import pdfplumber; print('pdfplumber OK')" +``` + +### LLM API 配置 + +翻译引擎首选 LLM(GPT-4 / Claude),在 `.env` 中配置: + +``` +OPENAI_API_KEY=sk-xxxxx +``` + +如果未配置 LLM API,将回退到 `deep-translator`(Google Translate / DeepL)。 + +--- + +## Instructions + +### 支持的语言 + +| 语言代码 | 语言 | 翻译质量 | +|---------|------|---------| +| `zh-CN` | 简体中文 | ★★★★★ | +| `zh-TW` | 繁体中文 | ★★★★★ | +| `en` | 英文 | ★★★★★ | +| `ja` | 日文 | ★★★★ | +| `ko` | 韩文 | ★★★★ | +| `fr` | 法文 | ★★★★ | +| `de` | 德文 | ★★★★ | +| `es` | 西班牙文 | ★★★★ | +| `ru` | 俄文 | ★★★ | +| `ar` | 阿拉伯文 | ★★★ | + +### 翻译引擎优先级 + +| 优先级 | 引擎 | 特点 | +|--------|------|------| +| 1 | LLM (GPT-4/Claude) | 最高质量,理解上下文,术语一致 | +| 2 | DeepL API | 高质量机器翻译 | +| 3 | Google Translate | 免费,覆盖语种广 | + +Agent 按照优先级自动选择可用的翻译引擎。用户可以指定使用特定引擎。 + +### PDF 元素处理策略 + +| 元素 | 处理方式 | +|------|---------| +| 正文文本 | 翻译并保留字体大小、颜色、粗体/斜体 | +| 标题 | 翻译并保留层级和样式 | +| 表格 | 翻译单元格内容,保留表格结构 | +| 图片 | 保留原图不动 | +| 图片中的文字 | 可选 OCR 识别后翻译 | +| 页眉/页脚 | 翻译并保持位置 | +| 页码 | 保持不变 | +| 脚注/尾注 | 翻译内容,保留编号 | +| 目录 | 翻译条目,页码不变 | +| 书签 | 翻译标题 | +| 链接/URL | 保持不变 | +| 数学公式 | 保持不变 | +| 代码块 | 保持不变(仅翻译注释) | +| 水印 | 保留原样 | + +--- + +## Workflows + +### Workflow 1: 标准 PDF 翻译 + +**步骤 1 — 解析 PDF 结构** + +```python +import fitz + +doc = fitz.open("input.pdf") +print(f"总页数: {doc.page_count}") +print(f"元数据: {doc.metadata}") + +for page_num in range(min(3, doc.page_count)): + page = doc[page_num] + text = page.get_text("dict") + print(f"第 {page_num + 1} 页: {len(text['blocks'])} 个文本块") +``` + +**步骤 2 — 逐页提取文本块** + +```python +def extract_text_blocks(page): + """提取页面中所有文本块及其位置和样式""" + blocks = [] + text_dict = page.get_text("dict") + + for block in text_dict["blocks"]: + if block["type"] == 0: # text block + for line in block["lines"]: + for span in line["spans"]: + blocks.append({ + "text": span["text"], + "bbox": span["bbox"], + "font": span["font"], + "size": span["size"], + "color": span["color"], + "flags": span["flags"], + }) + return blocks +``` + +**步骤 3 — 批量翻译** + +将提取的文本按段落分组,批量发送给翻译引擎: + +```python +async def translate_blocks(blocks, target_lang="zh-CN"): + paragraphs = merge_spans_to_paragraphs(blocks) + + translated = [] + for batch in chunk_list(paragraphs, batch_size=20): + texts = [p["text"] for p in batch] + results = await batch_translate(texts, target_lang) + translated.extend(results) + + return translated +``` + +**LLM 翻译 Prompt** + +``` +你是一位专业的文档翻译师。请将以下文本从{source_lang}翻译为{target_lang}。 + +要求: +1. 保持专业术语的准确性和一致性 +2. 保持段落结构不变 +3. 对于技术术语,首次出现时附上原文:如"卷积神经网络(CNN)" +4. 不翻译代码、公式、URL、人名(除非有通用中文译名) +5. 保持原文的语气和风格 + +待翻译文本: +--- +{text} +--- +``` + +**步骤 4 — 重建 PDF** + +```python +def rebuild_pdf(original_doc, translated_blocks, output_path): + """用翻译后的文本替换原文,保留排版""" + new_doc = fitz.open() + + for page_num in range(original_doc.page_count): + orig_page = original_doc[page_num] + new_page = new_doc.new_page( + width=orig_page.rect.width, + height=orig_page.rect.height + ) + + # 复制图片和非文本元素 + new_page.show_pdf_page(new_page.rect, original_doc, page_num) + + # 覆盖原文区域并写入译文 + for block in translated_blocks[page_num]: + rect = fitz.Rect(block["bbox"]) + new_page.draw_rect(rect, color=None, fill=(1, 1, 1)) + new_page.insert_textbox( + rect, + block["translated_text"], + fontsize=block["size"] * 0.85, + fontname="china-ss", + align=fitz.TEXT_ALIGN_LEFT + ) + + new_doc.save(output_path) +``` + +**步骤 5 — 质量检查** + +翻译完成后执行自动检查: +- 页数与原文一致 +- 无空白页面 +- 翻译覆盖率(已翻译文本 / 总文本 ≥ 95%) +- 字体渲染正常 + +--- + +### Workflow 2: 双语对照 PDF + +生成左右/上下对照的双语 PDF: + +**布局选项** + +| 布局 | 说明 | 适用场景 | +|------|------|---------| +| 左右对照 | 左页原文、右页译文 | 学术论文、对比审阅 | +| 上下对照 | 段落级交替显示 | 学习材料 | +| 注释模式 | 译文作为侧边注释 | 保留原文为主 | + +```python +def create_bilingual_pdf(original_doc, translated_blocks, output_path, layout="side-by-side"): + new_doc = fitz.open() + + for page_num in range(original_doc.page_count): + orig_page = original_doc[page_num] + + if layout == "side-by-side": + new_width = orig_page.rect.width * 2 + new_page = new_doc.new_page( + width=new_width, + height=orig_page.rect.height + ) + # 左侧放原文 + new_page.show_pdf_page( + fitz.Rect(0, 0, orig_page.rect.width, orig_page.rect.height), + original_doc, page_num + ) + # 右侧放译文 + insert_translated_page( + new_page, + translated_blocks[page_num], + offset_x=orig_page.rect.width + ) + + new_doc.save(output_path) +``` + +--- + +### Workflow 3: 扫描版 PDF 翻译(OCR) + +处理扫描件或图片型 PDF: + +**步骤 1 — 检测 PDF 类型** + +```python +def is_scanned_pdf(doc): + """检测 PDF 是否为扫描件""" + for page_num in range(min(3, doc.page_count)): + page = doc[page_num] + text = page.get_text().strip() + images = page.get_images() + if not text and images: + return True + return False +``` + +**步骤 2 — OCR 识别** + +```python +from pdf2image import convert_from_path +import pytesseract + +images = convert_from_path("scanned.pdf", dpi=300) +for i, img in enumerate(images): + text = pytesseract.image_to_string(img, lang='eng') + # 使用 image_to_data 获取文字位置信息 + data = pytesseract.image_to_data(img, lang='eng', output_type=pytesseract.Output.DICT) +``` + +**步骤 3** — 对 OCR 结果执行 Workflow 1 的翻译和重建流程 + +--- + +### Workflow 4: 批量 PDF 翻译 + +```python +import glob +import asyncio + +async def batch_translate_pdfs(input_dir, output_dir, target_lang="zh-CN"): + pdf_files = glob.glob(f"{input_dir}/*.pdf") + print(f"发现 {len(pdf_files)} 个 PDF 文件") + + for pdf_path in pdf_files: + output_path = os.path.join( + output_dir, + os.path.basename(pdf_path).replace('.pdf', f'_{target_lang}.pdf') + ) + print(f"翻译: {pdf_path} -> {output_path}") + await translate_single_pdf(pdf_path, output_path, target_lang) +``` + +--- + +## Output Format + +### 文件命名 + +``` +{原文件名}_{目标语言}.pdf +``` + +示例: +- `research_paper_zh-CN.pdf`(翻译版) +- `research_paper_bilingual.pdf`(双语版) + +### 输出报告 + +``` +📄 PDF 翻译完成 +- 原文件:research_paper.pdf (25 页) +- 译文件:research_paper_zh-CN.pdf (25 页) +- 源语言:English → 目标语言:简体中文 +- 翻译引擎:GPT-4 +- 翻译覆盖率:98.5% +- 表格数量:12 个(已翻译) +- 图片数量:8 张(已保留) +- 耗时:3 分 42 秒 +- 费用估算:$0.85 +``` + +--- + +## Common Pitfalls + +### 1. 中文字体缺失导致乱码 + +**症状**:翻译后的 PDF 中文显示为方框或乱码 +**解决**:确保系统安装了中文字体,并在 PyMuPDF 中注册: + +```python +import fitz + +# PyMuPDF 支持的中文字体 +# "china-ss" = 思源宋体 (简体) +# "china-ts" = 思源宋体 (繁体) +# 或使用自定义字体 +page.insert_font(fontname="custom-zh", fontfile="/path/to/NotoSansCJK-Regular.ttf") +``` + +### 2. 表格翻译后错位 + +**症状**:表格内容溢出单元格 +**原因**:中文译文通常比英文短,但某些情况下可能更长 +**解决**: +- 动态调整字体大小以适应单元格 +- 允许文本自动换行 +- 对于复杂表格,使用 pdfplumber 提取后单独翻译 + +### 3. 数学公式被错误翻译 + +**症状**:公式被当作文本翻译 +**解决**:在翻译前识别并标记数学公式区域,跳过翻译: + +```python +import re + +def should_skip_translation(text): + """判断文本是否应跳过翻译""" + # 数学公式模式 + if re.match(r'^[\s\d\+\-\*\/\=\(\)\[\]\{\}\^\_\\\$]+$', text): + return True + # LaTeX 公式 + if text.strip().startswith('\\') and not text.strip().startswith('\\text'): + return True + # 代码块 + if re.match(r'^(def |class |import |from |const |let |var |function )', text.strip()): + return True + return False +``` + +### 4. 大文件内存溢出 + +**症状**:处理超过 100 页的大型 PDF 时内存不足 +**解决**:逐页处理而非一次性加载: + +```python +for page_num in range(doc.page_count): + page = doc[page_num] + # 处理当前页 + process_page(page) + # 释放内存 + page = None +``` + +### 5. OCR 识别率低 + +**症状**:扫描版 PDF 的文字识别错误多 +**解决**: +- 提高扫描 DPI(≥ 300) +- 预处理图片(二值化、去噪、倾斜校正) +- 使用语言包:`pytesseract.image_to_string(img, lang='eng+chi_sim')` + +### 6. 翻译术语不一致 + +**症状**:同一术语在不同页面有不同翻译 +**解决**: +- 第一遍扫描时建立术语表 +- 将术语表作为上下文传递给 LLM +- 翻译后用脚本检查术语一致性 + +```python +glossary = { + "machine learning": "机器学习", + "neural network": "神经网络", + "gradient descent": "梯度下降", + "backpropagation": "反向传播", +} +``` + +### 7. 页眉页脚重复翻译 + +**症状**:每页的页眉页脚翻译结果微有差异 +**解决**:先识别页眉页脚模式,统一翻译一次后应用到所有页面 + +--- + +## 高级配置 + +### 翻译质量等级 + +| 等级 | 方式 | 速度 | 质量 | 费用 | +|------|------|------|------|------| +| 快速 | Google Translate | ★★★★★ | ★★★ | 免费 | +| 标准 | DeepL | ★★★★ | ★★★★ | $$ | +| 专业 | GPT-4 | ★★★ | ★★★★★ | $$$ | +| 人机协作 | GPT-4 + 人工审校 | ★★ | ★★★★★+ | $$$$ | + +### 自定义术语表 + +用户可提供术语表文件(CSV/JSON)确保特定术语的翻译一致: + +```json +{ + "source_lang": "en", + "target_lang": "zh-CN", + "terms": { + "OpenAkita": "OpenAkita", + "Agent": "智能体", + "fine-tuning": "微调", + "prompt engineering": "提示词工程" + } +} +``` + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 行业专用术语表 +- 首选翻译引擎和质量等级 +- 自定义字体路径 +- PDF 模板和样式覆盖规则 +- 特定文档类型的预处理规则 diff --git a/account/admin/skills/video-downloader/SKILL.md b/account/admin/skills/video-downloader/SKILL.md new file mode 100644 index 0000000..557cc84 --- /dev/null +++ b/account/admin/skills/video-downloader/SKILL.md @@ -0,0 +1,99 @@ +--- +name: openakita/skills@video-downloader +description: Download YouTube videos with customizable quality and format options. Use this skill when the user asks to download, save, or grab YouTube videos. Supports various quality settings (best, 1080p, 720p, 480p, 360p), multiple formats (mp4, webm, mkv), and audio-only downloads as MP3. +--- + +# YouTube Video Downloader + +Download YouTube videos with full control over quality and format settings. + +## Quick Start + +The simplest way to download a video: + +```bash +python scripts/download_video.py "https://www.youtube.com/watch?v=VIDEO_ID" +``` + +This downloads the video in best available quality as MP4 to `/mnt/user-data/outputs/`. + +## Options + +### Quality Settings + +Use `-q` or `--quality` to specify video quality: + +- `best` (default): Highest quality available +- `1080p`: Full HD +- `720p`: HD +- `480p`: Standard definition +- `360p`: Lower quality +- `worst`: Lowest quality available + +Example: +```bash +python scripts/download_video.py "URL" -q 720p +``` + +### Format Options + +Use `-f` or `--format` to specify output format (video downloads only): + +- `mp4` (default): Most compatible +- `webm`: Modern format +- `mkv`: Matroska container + +Example: +```bash +python scripts/download_video.py "URL" -f webm +``` + +### Audio Only + +Use `-a` or `--audio-only` to download only audio as MP3: + +```bash +python scripts/download_video.py "URL" -a +``` + +### Custom Output Directory + +Use `-o` or `--output` to specify a different output directory: + +```bash +python scripts/download_video.py "URL" -o /path/to/directory +``` + +## Complete Examples + +1. Download video in 1080p as MP4: +```bash +python scripts/download_video.py "https://www.youtube.com/watch?v=dQw4w9WgXcQ" -q 1080p +``` + +2. Download audio only as MP3: +```bash +python scripts/download_video.py "https://www.youtube.com/watch?v=dQw4w9WgXcQ" -a +``` + +3. Download in 720p as WebM to custom directory: +```bash +python scripts/download_video.py "https://www.youtube.com/watch?v=dQw4w9WgXcQ" -q 720p -f webm -o /custom/path +``` + +## How It Works + +The skill uses `yt-dlp`, a robust YouTube downloader that: +- Automatically installs itself if not present +- Fetches video information before downloading +- Selects the best available streams matching your criteria +- Merges video and audio streams when needed +- Supports a wide range of YouTube video formats + +## Important Notes + +- Downloads are saved to `/mnt/user-data/outputs/` by default +- Video filename is automatically generated from the video title +- The script handles installation of yt-dlp automatically +- Only single videos are downloaded (playlists are skipped by default) +- Higher quality videos may take longer to download and use more disk space \ No newline at end of file diff --git a/account/admin/skills/video-downloader/scripts/download_video.py b/account/admin/skills/video-downloader/scripts/download_video.py new file mode 100644 index 0000000..7202c74 --- /dev/null +++ b/account/admin/skills/video-downloader/scripts/download_video.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +""" +YouTube Video Downloader +Downloads videos from YouTube with customizable quality and format options. +""" + +import argparse +import sys +import subprocess +import json + + +def check_yt_dlp(): + """Check if yt-dlp is installed, install if not.""" + try: + subprocess.run(["yt-dlp", "--version"], capture_output=True, check=True) + except (subprocess.CalledProcessError, FileNotFoundError): + print("yt-dlp not found. Installing...") + subprocess.run([sys.executable, "-m", "pip", "install", "--break-system-packages", "yt-dlp"], check=True) + + +def get_video_info(url): + """Get information about the video without downloading.""" + result = subprocess.run( + ["yt-dlp", "--dump-json", "--no-playlist", url], + capture_output=True, + text=True, + check=True + ) + return json.loads(result.stdout) + + +def download_video(url, output_path="/mnt/user-data/outputs", quality="best", format_type="mp4", audio_only=False): + """ + Download a YouTube video. + + Args: + url: YouTube video URL + output_path: Directory to save the video + quality: Quality setting (best, 1080p, 720p, 480p, 360p, worst) + format_type: Output format (mp4, webm, mkv, etc.) + audio_only: Download only audio (mp3) + """ + check_yt_dlp() + + # Build command + cmd = ["yt-dlp"] + + if audio_only: + cmd.extend([ + "-x", # Extract audio + "--audio-format", "mp3", + "--audio-quality", "0", # Best quality + ]) + else: + # Video quality settings + if quality == "best": + format_string = "bestvideo+bestaudio/best" + elif quality == "worst": + format_string = "worstvideo+worstaudio/worst" + else: + # Specific resolution (e.g., 1080p, 720p) + height = quality.replace("p", "") + format_string = f"bestvideo[height<={height}]+bestaudio/best[height<={height}]" + + cmd.extend([ + "-f", format_string, + "--merge-output-format", format_type, + ]) + + # Output template + cmd.extend([ + "-o", f"{output_path}/%(title)s.%(ext)s", + "--no-playlist", # Don't download playlists by default + ]) + + cmd.append(url) + + print(f"Downloading from: {url}") + print(f"Quality: {quality}") + print(f"Format: {'mp3 (audio only)' if audio_only else format_type}") + print(f"Output: {output_path}\n") + + try: + # Get video info first + info = get_video_info(url) + print(f"Title: {info.get('title', 'Unknown')}") + print(f"Duration: {info.get('duration', 0) // 60}:{info.get('duration', 0) % 60:02d}") + print(f"Uploader: {info.get('uploader', 'Unknown')}\n") + + # Download the video + subprocess.run(cmd, check=True) + print(f"\n✅ Download complete!") + return True + except subprocess.CalledProcessError as e: + print(f"\n❌ Error downloading video: {e}") + return False + except Exception as e: + print(f"\n❌ Error: {e}") + return False + + +def main(): + parser = argparse.ArgumentParser( + description="Download YouTube videos with customizable quality and format" + ) + parser.add_argument("url", help="YouTube video URL") + parser.add_argument( + "-o", "--output", + default="/mnt/user-data/outputs", + help="Output directory (default: /mnt/user-data/outputs)" + ) + parser.add_argument( + "-q", "--quality", + default="best", + choices=["best", "1080p", "720p", "480p", "360p", "worst"], + help="Video quality (default: best)" + ) + parser.add_argument( + "-f", "--format", + default="mp4", + choices=["mp4", "webm", "mkv"], + help="Video format (default: mp4)" + ) + parser.add_argument( + "-a", "--audio-only", + action="store_true", + help="Download only audio as MP3" + ) + + args = parser.parse_args() + + success = download_video( + url=args.url, + output_path=args.output, + quality=args.quality, + format_type=args.format, + audio_only=args.audio_only + ) + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/account/admin/skills/web-artifacts-builder/LICENSE.txt b/account/admin/skills/web-artifacts-builder/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/web-artifacts-builder/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/web-artifacts-builder/SKILL.md b/account/admin/skills/web-artifacts-builder/SKILL.md new file mode 100644 index 0000000..c90b849 --- /dev/null +++ b/account/admin/skills/web-artifacts-builder/SKILL.md @@ -0,0 +1,74 @@ +--- +name: openakita/skills@web-artifacts-builder +description: Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts. +license: Complete terms in LICENSE.txt +--- + +# Web Artifacts Builder + +To build powerful frontend claude.ai artifacts, follow these steps: +1. Initialize the frontend repo using `scripts/init-artifact.sh` +2. Develop your artifact by editing the generated code +3. Bundle all code into a single HTML file using `scripts/bundle-artifact.sh` +4. Display artifact to user +5. (Optional) Test the artifact + +**Stack**: React 18 + TypeScript + Vite + Parcel (bundling) + Tailwind CSS + shadcn/ui + +## Design & Style Guidelines + +VERY IMPORTANT: To avoid what is often referred to as "AI slop", avoid using excessive centered layouts, purple gradients, uniform rounded corners, and Inter font. + +## Quick Start + +### Step 1: Initialize Project + +Run the initialization script to create a new React project: +```bash +bash scripts/init-artifact.sh <project-name> +cd <project-name> +``` + +This creates a fully configured project with: +- ✅ React + TypeScript (via Vite) +- ✅ Tailwind CSS 3.4.1 with shadcn/ui theming system +- ✅ Path aliases (`@/`) configured +- ✅ 40+ shadcn/ui components pre-installed +- ✅ All Radix UI dependencies included +- ✅ Parcel configured for bundling (via .parcelrc) +- ✅ Node 18+ compatibility (auto-detects and pins Vite version) + +### Step 2: Develop Your Artifact + +To build the artifact, edit the generated files. See **Common Development Tasks** below for guidance. + +### Step 3: Bundle to Single HTML File + +To bundle the React app into a single HTML artifact: +```bash +bash scripts/bundle-artifact.sh +``` + +This creates `bundle.html` - a self-contained artifact with all JavaScript, CSS, and dependencies inlined. This file can be directly shared in Claude conversations as an artifact. + +**Requirements**: Your project must have an `index.html` in the root directory. + +**What the script does**: +- Installs bundling dependencies (parcel, @parcel/config-default, parcel-resolver-tspaths, html-inline) +- Creates `.parcelrc` config with path alias support +- Builds with Parcel (no source maps) +- Inlines all assets into single HTML using html-inline + +### Step 4: Share Artifact with User + +Finally, share the bundled HTML file in conversation with the user so they can view it as an artifact. + +### Step 5: Testing/Visualizing the Artifact (Optional) + +Note: This is a completely optional step. Only perform if necessary or requested. + +To test/visualize the artifact, use available tools (including other Skills or built-in tools like Playwright or Puppeteer). In general, avoid testing the artifact upfront as it adds latency between the request and when the finished artifact can be seen. Test later, after presenting the artifact, if requested or if issues arise. + +## Reference + +- **shadcn/ui components**: https://ui.shadcn.com/docs/components \ No newline at end of file diff --git a/account/admin/skills/web-artifacts-builder/scripts/bundle-artifact.sh b/account/admin/skills/web-artifacts-builder/scripts/bundle-artifact.sh new file mode 100644 index 0000000..c13d229 --- /dev/null +++ b/account/admin/skills/web-artifacts-builder/scripts/bundle-artifact.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -e + +echo "📦 Bundling React app to single HTML artifact..." + +# Check if we're in a project directory +if [ ! -f "package.json" ]; then + echo "❌ Error: No package.json found. Run this script from your project root." + exit 1 +fi + +# Check if index.html exists +if [ ! -f "index.html" ]; then + echo "❌ Error: No index.html found in project root." + echo " This script requires an index.html entry point." + exit 1 +fi + +# Install bundling dependencies +echo "📦 Installing bundling dependencies..." +pnpm add -D parcel @parcel/config-default parcel-resolver-tspaths html-inline + +# Create Parcel config with tspaths resolver +if [ ! -f ".parcelrc" ]; then + echo "🔧 Creating Parcel configuration with path alias support..." + cat > .parcelrc << 'EOF' +{ + "extends": "@parcel/config-default", + "resolvers": ["parcel-resolver-tspaths", "..."] +} +EOF +fi + +# Clean previous build +echo "🧹 Cleaning previous build..." +rm -rf dist bundle.html + +# Build with Parcel +echo "🔨 Building with Parcel..." +pnpm exec parcel build index.html --dist-dir dist --no-source-maps + +# Inline everything into single HTML +echo "🎯 Inlining all assets into single HTML file..." +pnpm exec html-inline dist/index.html > bundle.html + +# Get file size +FILE_SIZE=$(du -h bundle.html | cut -f1) + +echo "" +echo "✅ Bundle complete!" +echo "📄 Output: bundle.html ($FILE_SIZE)" +echo "" +echo "You can now use this single HTML file as an artifact in Claude conversations." +echo "To test locally: open bundle.html in your browser" \ No newline at end of file diff --git a/account/admin/skills/web-artifacts-builder/scripts/init-artifact.sh b/account/admin/skills/web-artifacts-builder/scripts/init-artifact.sh new file mode 100644 index 0000000..7d1022d --- /dev/null +++ b/account/admin/skills/web-artifacts-builder/scripts/init-artifact.sh @@ -0,0 +1,322 @@ +#!/bin/bash + +# Exit on error +set -e + +# Detect Node version +NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) + +echo "🔍 Detected Node.js version: $NODE_VERSION" + +if [ "$NODE_VERSION" -lt 18 ]; then + echo "❌ Error: Node.js 18 or higher is required" + echo " Current version: $(node -v)" + exit 1 +fi + +# Set Vite version based on Node version +if [ "$NODE_VERSION" -ge 20 ]; then + VITE_VERSION="latest" + echo "✅ Using Vite latest (Node 20+)" +else + VITE_VERSION="5.4.11" + echo "✅ Using Vite $VITE_VERSION (Node 18 compatible)" +fi + +# Detect OS and set sed syntax +if [[ "$OSTYPE" == "darwin"* ]]; then + SED_INPLACE="sed -i ''" +else + SED_INPLACE="sed -i" +fi + +# Check if pnpm is installed +if ! command -v pnpm &> /dev/null; then + echo "📦 pnpm not found. Installing pnpm..." + npm install -g pnpm +fi + +# Check if project name is provided +if [ -z "$1" ]; then + echo "❌ Usage: ./create-react-shadcn-complete.sh <project-name>" + exit 1 +fi + +PROJECT_NAME="$1" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPONENTS_TARBALL="$SCRIPT_DIR/shadcn-components.tar.gz" + +# Check if components tarball exists +if [ ! -f "$COMPONENTS_TARBALL" ]; then + echo "❌ Error: shadcn-components.tar.gz not found in script directory" + echo " Expected location: $COMPONENTS_TARBALL" + exit 1 +fi + +echo "🚀 Creating new React + Vite project: $PROJECT_NAME" + +# Create new Vite project (always use latest create-vite, pin vite version later) +pnpm create vite "$PROJECT_NAME" --template react-ts + +# Navigate into project directory +cd "$PROJECT_NAME" + +echo "🧹 Cleaning up Vite template..." +$SED_INPLACE '/<link rel="icon".*vite\.svg/d' index.html +$SED_INPLACE 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html + +echo "📦 Installing base dependencies..." +pnpm install + +# Pin Vite version for Node 18 +if [ "$NODE_VERSION" -lt 20 ]; then + echo "📌 Pinning Vite to $VITE_VERSION for Node 18 compatibility..." + pnpm add -D vite@$VITE_VERSION +fi + +echo "📦 Installing Tailwind CSS and dependencies..." +pnpm install -D tailwindcss@3.4.1 postcss autoprefixer @types/node tailwindcss-animate +pnpm install class-variance-authority clsx tailwind-merge lucide-react next-themes + +echo "⚙️ Creating Tailwind and PostCSS configuration..." +cat > postcss.config.js << 'EOF' +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} +EOF + +echo "📝 Configuring Tailwind with shadcn theme..." +cat > tailwind.config.js << 'EOF' +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ["class"], + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} +EOF + +# Add Tailwind directives and CSS variables to index.css +echo "🎨 Adding Tailwind directives and CSS variables..." +cat > src/index.css << 'EOF' +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} +EOF + +# Add path aliases to tsconfig.json +echo "🔧 Adding path aliases to tsconfig.json..." +node -e " +const fs = require('fs'); +const config = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8')); +config.compilerOptions = config.compilerOptions || {}; +config.compilerOptions.baseUrl = '.'; +config.compilerOptions.paths = { '@/*': ['./src/*'] }; +fs.writeFileSync('tsconfig.json', JSON.stringify(config, null, 2)); +" + +# Add path aliases to tsconfig.app.json +echo "🔧 Adding path aliases to tsconfig.app.json..." +node -e " +const fs = require('fs'); +const path = 'tsconfig.app.json'; +const content = fs.readFileSync(path, 'utf8'); +// Remove comments manually +const lines = content.split('\n').filter(line => !line.trim().startsWith('//')); +const jsonContent = lines.join('\n'); +const config = JSON.parse(jsonContent.replace(/\/\*[\s\S]*?\*\//g, '').replace(/,(\s*[}\]])/g, '\$1')); +config.compilerOptions = config.compilerOptions || {}; +config.compilerOptions.baseUrl = '.'; +config.compilerOptions.paths = { '@/*': ['./src/*'] }; +fs.writeFileSync(path, JSON.stringify(config, null, 2)); +" + +# Update vite.config.ts +echo "⚙️ Updating Vite configuration..." +cat > vite.config.ts << 'EOF' +import path from "path"; +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, +}); +EOF + +# Install all shadcn/ui dependencies +echo "📦 Installing shadcn/ui dependencies..." +pnpm install @radix-ui/react-accordion @radix-ui/react-aspect-ratio @radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-collapsible @radix-ui/react-context-menu @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-hover-card @radix-ui/react-label @radix-ui/react-menubar @radix-ui/react-navigation-menu @radix-ui/react-popover @radix-ui/react-progress @radix-ui/react-radio-group @radix-ui/react-scroll-area @radix-ui/react-select @radix-ui/react-separator @radix-ui/react-slider @radix-ui/react-slot @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-toast @radix-ui/react-toggle @radix-ui/react-toggle-group @radix-ui/react-tooltip +pnpm install sonner cmdk vaul embla-carousel-react react-day-picker react-resizable-panels date-fns react-hook-form @hookform/resolvers zod + +# Extract shadcn components from tarball +echo "📦 Extracting shadcn/ui components..." +tar -xzf "$COMPONENTS_TARBALL" -C src/ + +# Create components.json for reference +echo "📝 Creating components.json config..." +cat > components.json << 'EOF' +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + } +} +EOF + +echo "✅ Setup complete! You can now use Tailwind CSS and shadcn/ui in your project." +echo "" +echo "📦 Included components (40+ total):" +echo " - accordion, alert, aspect-ratio, avatar, badge, breadcrumb" +echo " - button, calendar, card, carousel, checkbox, collapsible" +echo " - command, context-menu, dialog, drawer, dropdown-menu" +echo " - form, hover-card, input, label, menubar, navigation-menu" +echo " - popover, progress, radio-group, resizable, scroll-area" +echo " - select, separator, sheet, skeleton, slider, sonner" +echo " - switch, table, tabs, textarea, toast, toggle, toggle-group, tooltip" +echo "" +echo "To start developing:" +echo " cd $PROJECT_NAME" +echo " pnpm dev" +echo "" +echo "📚 Import components like:" +echo " import { Button } from '@/components/ui/button'" +echo " import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'" +echo " import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog'" diff --git a/account/admin/skills/webapp-testing/LICENSE.txt b/account/admin/skills/webapp-testing/LICENSE.txt new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/account/admin/skills/webapp-testing/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/account/admin/skills/webapp-testing/SKILL.md b/account/admin/skills/webapp-testing/SKILL.md new file mode 100644 index 0000000..d41033a --- /dev/null +++ b/account/admin/skills/webapp-testing/SKILL.md @@ -0,0 +1,96 @@ +--- +name: openakita/skills@webapp-testing +description: Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs. +license: Complete terms in LICENSE.txt +--- + +# Web Application Testing + +To test local web applications, write native Python Playwright scripts. + +**Helper Scripts Available**: +- `scripts/with_server.py` - Manages server lifecycle (supports multiple servers) + +**Always run scripts with `--help` first** to see usage. DO NOT read the source until you try running the script first and find that a customized solution is abslutely necessary. These scripts can be very large and thus pollute your context window. They exist to be called directly as black-box scripts rather than ingested into your context window. + +## Decision Tree: Choosing Your Approach + +``` +User task → Is it static HTML? + ├─ Yes → Read HTML file directly to identify selectors + │ ├─ Success → Write Playwright script using selectors + │ └─ Fails/Incomplete → Treat as dynamic (below) + │ + └─ No (dynamic webapp) → Is the server already running? + ├─ No → Run: python scripts/with_server.py --help + │ Then use the helper + write simplified Playwright script + │ + └─ Yes → Reconnaissance-then-action: + 1. Navigate and wait for networkidle + 2. Take screenshot or inspect DOM + 3. Identify selectors from rendered state + 4. Execute actions with discovered selectors +``` + +## Example: Using with_server.py + +To start a server, run `--help` first, then use the helper: + +**Single server:** +```bash +python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py +``` + +**Multiple servers (e.g., backend + frontend):** +```bash +python scripts/with_server.py \ + --server "cd backend && python server.py" --port 3000 \ + --server "cd frontend && npm run dev" --port 5173 \ + -- python your_automation.py +``` + +To create an automation script, include only Playwright logic (servers are managed automatically): +```python +from playwright.sync_api import sync_playwright + +with sync_playwright() as p: + browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode + page = browser.new_page() + page.goto('http://localhost:5173') # Server already running and ready + page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute + # ... your automation logic + browser.close() +``` + +## Reconnaissance-Then-Action Pattern + +1. **Inspect rendered DOM**: + ```python + page.screenshot(path='/tmp/inspect.png', full_page=True) + content = page.content() + page.locator('button').all() + ``` + +2. **Identify selectors** from inspection results + +3. **Execute actions** using discovered selectors + +## Common Pitfall + +❌ **Don't** inspect the DOM before waiting for `networkidle` on dynamic apps +✅ **Do** wait for `page.wait_for_load_state('networkidle')` before inspection + +## Best Practices + +- **Use bundled scripts as black boxes** - To accomplish a task, consider whether one of the scripts available in `scripts/` can help. These scripts handle common, complex workflows reliably without cluttering the context window. Use `--help` to see usage, then invoke directly. +- Use `sync_playwright()` for synchronous scripts +- Always close the browser when done +- Use descriptive selectors: `text=`, `role=`, CSS selectors, or IDs +- Add appropriate waits: `page.wait_for_selector()` or `page.wait_for_timeout()` + +## Reference Files + +- **examples/** - Examples showing common patterns: + - `element_discovery.py` - Discovering buttons, links, and inputs on a page + - `static_html_automation.py` - Using file:// URLs for local HTML + - `console_logging.py` - Capturing console logs during automation \ No newline at end of file diff --git a/account/admin/skills/webapp-testing/examples/console_logging.py b/account/admin/skills/webapp-testing/examples/console_logging.py new file mode 100644 index 0000000..9329b5e --- /dev/null +++ b/account/admin/skills/webapp-testing/examples/console_logging.py @@ -0,0 +1,35 @@ +from playwright.sync_api import sync_playwright + +# Example: Capturing console logs during browser automation + +url = 'http://localhost:5173' # Replace with your URL + +console_logs = [] + +with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={'width': 1920, 'height': 1080}) + + # Set up console log capture + def handle_console_message(msg): + console_logs.append(f"[{msg.type}] {msg.text}") + print(f"Console: [{msg.type}] {msg.text}") + + page.on("console", handle_console_message) + + # Navigate to page + page.goto(url) + page.wait_for_load_state('networkidle') + + # Interact with the page (triggers console logs) + page.click('text=Dashboard') + page.wait_for_timeout(1000) + + browser.close() + +# Save console logs to file +with open('/mnt/user-data/outputs/console.log', 'w') as f: + f.write('\n'.join(console_logs)) + +print(f"\nCaptured {len(console_logs)} console messages") +print(f"Logs saved to: /mnt/user-data/outputs/console.log") \ No newline at end of file diff --git a/account/admin/skills/webapp-testing/examples/element_discovery.py b/account/admin/skills/webapp-testing/examples/element_discovery.py new file mode 100644 index 0000000..917ba72 --- /dev/null +++ b/account/admin/skills/webapp-testing/examples/element_discovery.py @@ -0,0 +1,40 @@ +from playwright.sync_api import sync_playwright + +# Example: Discovering buttons and other elements on a page + +with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page() + + # Navigate to page and wait for it to fully load + page.goto('http://localhost:5173') + page.wait_for_load_state('networkidle') + + # Discover all buttons on the page + buttons = page.locator('button').all() + print(f"Found {len(buttons)} buttons:") + for i, button in enumerate(buttons): + text = button.inner_text() if button.is_visible() else "[hidden]" + print(f" [{i}] {text}") + + # Discover links + links = page.locator('a[href]').all() + print(f"\nFound {len(links)} links:") + for link in links[:5]: # Show first 5 + text = link.inner_text().strip() + href = link.get_attribute('href') + print(f" - {text} -> {href}") + + # Discover input fields + inputs = page.locator('input, textarea, select').all() + print(f"\nFound {len(inputs)} input fields:") + for input_elem in inputs: + name = input_elem.get_attribute('name') or input_elem.get_attribute('id') or "[unnamed]" + input_type = input_elem.get_attribute('type') or 'text' + print(f" - {name} ({input_type})") + + # Take screenshot for visual reference + page.screenshot(path='/tmp/page_discovery.png', full_page=True) + print("\nScreenshot saved to /tmp/page_discovery.png") + + browser.close() \ No newline at end of file diff --git a/account/admin/skills/webapp-testing/examples/static_html_automation.py b/account/admin/skills/webapp-testing/examples/static_html_automation.py new file mode 100644 index 0000000..90bbedc --- /dev/null +++ b/account/admin/skills/webapp-testing/examples/static_html_automation.py @@ -0,0 +1,33 @@ +from playwright.sync_api import sync_playwright +import os + +# Example: Automating interaction with static HTML files using file:// URLs + +html_file_path = os.path.abspath('path/to/your/file.html') +file_url = f'file://{html_file_path}' + +with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={'width': 1920, 'height': 1080}) + + # Navigate to local HTML file + page.goto(file_url) + + # Take screenshot + page.screenshot(path='/mnt/user-data/outputs/static_page.png', full_page=True) + + # Interact with elements + page.click('text=Click Me') + page.fill('#name', 'John Doe') + page.fill('#email', 'john@example.com') + + # Submit form + page.click('button[type="submit"]') + page.wait_for_timeout(500) + + # Take final screenshot + page.screenshot(path='/mnt/user-data/outputs/after_submit.png', full_page=True) + + browser.close() + +print("Static HTML automation completed!") \ No newline at end of file diff --git a/account/admin/skills/webapp-testing/scripts/with_server.py b/account/admin/skills/webapp-testing/scripts/with_server.py new file mode 100644 index 0000000..431f2eb --- /dev/null +++ b/account/admin/skills/webapp-testing/scripts/with_server.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +""" +Start one or more servers, wait for them to be ready, run a command, then clean up. + +Usage: + # Single server + python scripts/with_server.py --server "npm run dev" --port 5173 -- python automation.py + python scripts/with_server.py --server "npm start" --port 3000 -- python test.py + + # Multiple servers + python scripts/with_server.py \ + --server "cd backend && python server.py" --port 3000 \ + --server "cd frontend && npm run dev" --port 5173 \ + -- python test.py +""" + +import subprocess +import socket +import time +import sys +import argparse + +def is_server_ready(port, timeout=30): + """Wait for server to be ready by polling the port.""" + start_time = time.time() + while time.time() - start_time < timeout: + try: + with socket.create_connection(('localhost', port), timeout=1): + return True + except (socket.error, ConnectionRefusedError): + time.sleep(0.5) + return False + + +def main(): + parser = argparse.ArgumentParser(description='Run command with one or more servers') + parser.add_argument('--server', action='append', dest='servers', required=True, help='Server command (can be repeated)') + parser.add_argument('--port', action='append', dest='ports', type=int, required=True, help='Port for each server (must match --server count)') + parser.add_argument('--timeout', type=int, default=30, help='Timeout in seconds per server (default: 30)') + parser.add_argument('command', nargs=argparse.REMAINDER, help='Command to run after server(s) ready') + + args = parser.parse_args() + + # Remove the '--' separator if present + if args.command and args.command[0] == '--': + args.command = args.command[1:] + + if not args.command: + print("Error: No command specified to run") + sys.exit(1) + + # Parse server configurations + if len(args.servers) != len(args.ports): + print("Error: Number of --server and --port arguments must match") + sys.exit(1) + + servers = [] + for cmd, port in zip(args.servers, args.ports): + servers.append({'cmd': cmd, 'port': port}) + + server_processes = [] + + try: + # Start all servers + for i, server in enumerate(servers): + print(f"Starting server {i+1}/{len(servers)}: {server['cmd']}") + + # Use shell=True to support commands with cd and && + process = subprocess.Popen( + server['cmd'], + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + server_processes.append(process) + + # Wait for this server to be ready + print(f"Waiting for server on port {server['port']}...") + if not is_server_ready(server['port'], timeout=args.timeout): + raise RuntimeError(f"Server failed to start on port {server['port']} within {args.timeout}s") + + print(f"Server ready on port {server['port']}") + + print(f"\nAll {len(servers)} server(s) ready") + + # Run the command + print(f"Running: {' '.join(args.command)}\n") + result = subprocess.run(args.command) + sys.exit(result.returncode) + + finally: + # Clean up all servers + print(f"\nStopping {len(server_processes)} server(s)...") + for i, process in enumerate(server_processes): + try: + process.terminate() + process.wait(timeout=5) + except subprocess.TimeoutExpired: + process.kill() + process.wait() + print(f"Server {i+1} stopped") + print("All servers stopped") + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/account/admin/skills/wechat-article/.openakita-i18n.json b/account/admin/skills/wechat-article/.openakita-i18n.json new file mode 100644 index 0000000..b7ad9ce --- /dev/null +++ b/account/admin/skills/wechat-article/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "公众号文章发布", + "description": "微信公众号文章创作与排版助手,支持 Markdown 转微信 HTML、富文本样式、封面设计、摘要生成,以及 API 和手动两种发布工作流。" + } +} diff --git a/account/admin/skills/wechat-article/SKILL.md b/account/admin/skills/wechat-article/SKILL.md new file mode 100644 index 0000000..1e1a381 --- /dev/null +++ b/account/admin/skills/wechat-article/SKILL.md @@ -0,0 +1,471 @@ +--- +name: openakita/skills@wechat-article +description: Create and format WeChat Official Account (公众号) articles with proper Markdown-to-WeChat HTML conversion, rich formatting, cover image guidance, and both API and manual publishing workflows. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# 微信公众号文章发布助手 + +专为微信公众号内容创作和发布打造的技能,提供从写作到排版到发布的全流程支持,包括 Markdown 转换、富文本样式、封面设计和摘要生成。 + +## 适用场景 + +- 撰写公众号原创文章(深度长文、观点评论、行业分析) +- Markdown 文章转微信公众号格式 +- 文章排版美化和样式优化 +- 封面图选择和摘要生成 +- 多平台内容适配(将博客/知乎内容转公众号格式) +- 通过 API 批量发布文章 +- 手动复制粘贴发布的格式优化 + +## Markdown 转微信 HTML 规范 + +### 转换核心原理 + +微信公众号编辑器不支持标准 Markdown,需要将 Markdown 转为内联样式的 HTML。关键限制: + +- **不支持** `<style>` 标签和外部 CSS +- **不支持** `class` 属性 +- **所有样式必须内联**(`style="..."` 属性) +- 图片必须上传到微信素材库(外链图片无法显示) +- 不支持 JavaScript + +### 基础元素转换表 + +| Markdown | 微信 HTML | +|----------|----------| +| `# 标题` | `<h1 style="font-size:22px;font-weight:bold;color:#333;border-bottom:2px solid #f0b849;padding-bottom:8px;">标题</h1>` | +| `## 标题` | `<h2 style="font-size:18px;font-weight:bold;color:#333;margin-top:24px;">标题</h2>` | +| `**粗体**` | `<strong style="color:#f0b849;">粗体</strong>` | +| `> 引用` | 使用金色引用框(见下方) | +| `` `代码` `` | `<code style="background:#f5f5f5;padding:2px 6px;border-radius:3px;font-size:14px;color:#c7254e;">代码</code>` | +| `---` | `<hr style="border:none;border-top:1px dashed #ddd;margin:24px 0;">` | +| `[链接](url)` | `<a style="color:#576b95;text-decoration:none;">链接文字</a>`(微信不支持外链,仅用于阅读原文) | + +### 金色引用框(标志性样式) + +```html +<blockquote style=" + border-left: 4px solid #f0b849; + background: linear-gradient(to right, #fdf8e8, #ffffff); + padding: 16px 20px; + margin: 16px 0; + border-radius: 0 8px 8px 0; + font-size: 15px; + color: #666; + line-height: 1.8; +"> + 引用内容 +</blockquote> +``` + +### 段落分隔线 + +```html +<!-- 简约分隔线 --> +<p style="text-align:center;color:#f0b849;font-size:16px;margin:20px 0;"> + ✦ ✦ ✦ +</p> + +<!-- 虚线分隔 --> +<hr style="border:none;border-top:1px dashed #e0e0e0;margin:24px 0;"> + +<!-- 图形分隔线 --> +<p style="text-align:center;color:#ccc;font-size:12px;letter-spacing:8px;margin:24px 0;"> + ◆◇◆◇◆ +</p> +``` + +## 公众号排版规范 + +### 一、正文排版 + +**字体和间距:** +```html +<section style=" + font-size: 15px; + color: #3f3f3f; + line-height: 1.8; + letter-spacing: 0.5px; + word-spacing: 2px; + text-align: justify; + padding: 0 8px; +"> + 正文内容 +</section> +``` + +**排版核心参数:** + +| 参数 | 推荐值 | 说明 | +|------|--------|------| +| 正文字号 | 15px | 移动端最佳阅读大小 | +| 行间距 | 1.8 | 阅读舒适度最佳 | +| 字间距 | 0.5px | 增加空气感 | +| 段间距 | 16px | 段落间留白 | +| 两侧留白 | 8px | 正文区域内缩 | +| 正文颜色 | #3f3f3f | 深灰,柔和不刺眼 | +| 强调色 | #f0b849 | 金色,品牌感 | + +### 二、标题层级样式 + +**一级标题(文章主标题):** +```html +<h1 style=" + font-size: 22px; + font-weight: bold; + color: #1a1a1a; + text-align: center; + margin: 32px 0 16px; + line-height: 1.4; +">文章标题</h1> +``` + +**二级标题(章节):** +```html +<h2 style=" + font-size: 18px; + font-weight: bold; + color: #333; + border-left: 4px solid #f0b849; + padding-left: 12px; + margin: 28px 0 12px; + line-height: 1.5; +">章节标题</h2> +``` + +**三级标题(小节):** +```html +<h3 style=" + font-size: 16px; + font-weight: bold; + color: #555; + margin: 20px 0 8px; + line-height: 1.5; +">小节标题</h3> +``` + +### 三、特殊排版组件 + +**高亮信息框:** +```html +<section style=" + background: #fffbeb; + border: 1px solid #f0b849; + border-radius: 8px; + padding: 16px; + margin: 16px 0; +"> + <p style="font-weight:bold;color:#f0a000;margin-bottom:8px;">💡 提示</p> + <p style="font-size:14px;color:#666;line-height:1.6;">提示内容</p> +</section> +``` + +**编号列表(带样式):** +```html +<section style="margin:12px 0;display:flex;align-items:flex-start;"> + <span style=" + display:inline-block; + width:24px;height:24px; + background:#f0b849; + color:#fff; + border-radius:50%; + text-align:center; + line-height:24px; + font-size:13px; + font-weight:bold; + margin-right:12px; + flex-shrink:0; + ">1</span> + <span style="font-size:15px;color:#3f3f3f;line-height:1.8;">列表项内容</span> +</section> +``` + +**图片标注:** +```html +<figure style="text-align:center;margin:20px 0;"> + <img src="[图片链接]" style="max-width:100%;border-radius:8px;"> + <figcaption style=" + font-size:12px; + color:#999; + margin-top:8px; + line-height:1.5; + ">图片说明文字</figcaption> +</figure> +``` + +## 封面图设计 + +### 尺寸规范 + +| 类型 | 尺寸 | 比例 | 用途 | +|------|------|------|------| +| 头条封面 | 900×383 px | 2.35:1 | 第一条推文 | +| 次条封面 | 500×500 px | 1:1 | 第二条及之后 | +| 文章头图 | 1080×608 px | 16:9 | 文章顶部大图 | + +### 封面设计原则 + +1. **文字清晰**:标题字号至少 40px,确保缩略图可读 +2. **色彩醒目**:高对比度,避免纯白背景 +3. **主题鲜明**:一眼看出文章主题 +4. **风格统一**:建立账号视觉识别体系 +5. **留白适当**:避免信息过载 + +### 封面文字排版公式 + +``` +主标题(大字)+ 副标题/关键词(小字)+ 品牌标识(角落) +``` + +## 摘要生成规范 + +公众号摘要显示在推送消息和分享卡片中,最多 **120 字**。 + +**摘要写作原则:** +- 第一句概括文章核心价值 +- 包含 1-2 个关键词(SEO) +- 制造悬念或给出利益点 +- 避免重复标题内容 + +**模板:** +``` +[核心观点/发现]。本文从[角度1]、[角度2]等方面深入分析, +并提供[具体价值]。适合[目标读者]阅读。 +``` + +## 发布工作流 + +### 方式一:API 自动发布(推荐) + +适用于有微信公众号开发者权限的用户。 + +``` +Step 1: Markdown 文章 → 微信 HTML 格式转换 + ↓ +Step 2: 图片资源上传至微信素材库 + - 调用素材管理接口上传图片 + - 获取 media_id 替换图片链接 + ↓ +Step 3: 生成封面图 + 摘要 + ↓ +Step 4: 创建图文素材(draft) + - POST /cgi-bin/draft/add + - 参数:title, content, digest, thumb_media_id + ↓ +Step 5: 预览验证 + - POST /cgi-bin/message/mass/preview + - 发送到指定微信号预览 + ↓ +Step 6: 群发或定时发布 + - POST /cgi-bin/freepublish/submit +``` + +**关键 API 端点:** + +| 接口 | 用途 | +|------|------| +| `POST /cgi-bin/material/add_material` | 上传永久素材 | +| `POST /cgi-bin/media/uploadimg` | 上传文章内图片 | +| `POST /cgi-bin/draft/add` | 新建草稿 | +| `POST /cgi-bin/draft/update` | 更新草稿 | +| `POST /cgi-bin/freepublish/submit` | 发布 | +| `POST /cgi-bin/message/mass/preview` | 预览 | + +### 方式二:手动发布 + +适用于无 API 权限或偶尔发布的用户。 + +``` +Step 1: 生成微信 HTML 格式内容 + ↓ +Step 2: 复制 HTML 到微信公众号后台编辑器 + - 打开 mp.weixin.qq.com → 内容管理 → 新建图文 + - 切换到「代码编辑」模式(</>按钮) + - 粘贴 HTML 代码 + ↓ +Step 3: 切回「可视化编辑」模式检查排版 + - 确认标题样式正确 + - 确认图片正常显示 + - 确认引用框和分隔线样式 + ↓ +Step 4: 上传封面图、填写摘要 + ↓ +Step 5: 预览 → 手机端检查 → 发布 +``` + +**手动发布注意事项:** +- HTML 中的图片需提前上传到微信素材库 +- 外链图片不会显示(微信安全策略) +- 粘贴后检查是否有样式丢失 +- 建议先在手机端预览再发布 + +## 常用排版模板 + +### 模板一:深度长文 + +``` +[文章头图] +[标题] +[作者信息/引言] +[金色分隔线] +[目录/导读] +[分隔线] +[正文章节 1] +[章节间分隔] +[正文章节 2] +... +[金色引用框总结] +[CTA/作者介绍] +[往期推荐] +``` + +### 模板二:清单推荐 + +``` +[封面] +[标题] +[一句话导语] +[分隔线] +[推荐项 1:编号 + 图片 + 描述] +[推荐项 2] +... +[总结对比表格] +[CTA] +``` + +### 模板三:教程指南 + +``` +[封面] +[标题] +[前置说明/工具准备] +[分隔线] +[Step 1 + 配图] +[Step 2 + 配图] +... +[常见问题 FAQ] +[CTA] +``` + +## 完整示例 + +### 示例:技术博客转公众号 + +**输入 Markdown:** +```markdown +# 2026 年前端性能优化指南 + +> 性能不是锦上添花,而是用户体验的基石。 + +## 为什么性能很重要 + +根据 Google 的研究,页面加载时间超过 **3秒**, +53% 的移动用户会离开。 +``` + +**转换后微信 HTML:** +```html +<h1 style="font-size:22px;font-weight:bold;color:#1a1a1a; + text-align:center;margin:32px 0 16px;line-height:1.4;"> + 2026 年前端性能优化指南 +</h1> + +<blockquote style="border-left:4px solid #f0b849; + background:linear-gradient(to right,#fdf8e8,#ffffff); + padding:16px 20px;margin:16px 0;border-radius:0 8px 8px 0; + font-size:15px;color:#666;line-height:1.8;"> + 性能不是锦上添花,而是用户体验的基石。 +</blockquote> + +<p style="text-align:center;color:#f0b849;font-size:16px; + margin:20px 0;">✦ ✦ ✦</p> + +<h2 style="font-size:18px;font-weight:bold;color:#333; + border-left:4px solid #f0b849;padding-left:12px; + margin:28px 0 12px;line-height:1.5;"> + 为什么性能很重要 +</h2> + +<section style="font-size:15px;color:#3f3f3f;line-height:1.8; + letter-spacing:0.5px;"> + <p>根据 Google 的研究,页面加载时间超过 + <strong style="color:#f0b849;">3秒</strong>, + 53% 的移动用户会离开。</p> +</section> +``` + +## 常见问题 + +| 问题 | 原因 | 解决方案 | +|------|------|---------| +| 图片不显示 | 使用了外链图片 | 上传到微信素材库,使用微信图片链接 | +| 样式丢失 | 使用了 class 或外部 CSS | 所有样式改为内联 style 属性 | +| 排版错乱 | HTML 标签嵌套错误 | 检查标签闭合,简化嵌套层级 | +| 链接无法点击 | 微信限制外链 | 使用「阅读原文」放置唯一外链 | +| 代码块不美观 | 微信不支持语法高亮 | 用背景色块+内联样式模拟代码块 | +| 表格显示不全 | 宽表格溢出 | 控制列数,或用列表替代表格 | + +## 写作建议 + +### 标题优化 + +- 字数控制在 **15-30 字** +- 包含核心关键词 +- 使用数字增加具体感(`7个方法`、`3分钟学会`) +- 适当使用竖线分隔(`前端优化 | 你必须知道的 7 个技巧`) + +### 开头黄金三行 + +读者在 3 秒内决定是否继续阅读,开头必须有冲击力: + +1. **数据开头**:`据统计,90% 的用户...` +2. **痛点开头**:`你是否也遇到过...` +3. **故事开头**:`上周,一个同事问我...` +4. **观点开头**:`我一直认为...直到...` + +### 结尾引导 + +- 总结全文核心观点 +- 引导点赞/在看/分享 +- 预告下期内容 +- 引导关注/加群 + +## 多平台适配 + +将公众号内容适配到其他平台的要点: + +| 平台 | 调整方向 | +|------|---------| +| 知乎 | 增加专业深度,添加引用来源 | +| 掘金/SegmentFault | 增加代码示例,技术细节 | +| 小红书 | 缩短到 500 字,增加 emoji 和视觉 | +| 头条号 | 增加标题党元素,分段更密 | + +## 输出格式 + +每次生成公众号内容时,按以下结构输出: + +```markdown +## 📰 公众号文章 + +### 基础信息 +- 标题:[标题] +- 摘要:[120字以内] +- 封面建议:[尺寸+风格] + +### 文章内容(微信 HTML) +[完整 HTML 代码] + +### 文章内容(Markdown 备份) +[Markdown 版本,便于其他平台使用] + +### 发布检查清单 +- [ ] 图片已上传素材库 +- [ ] 手机端预览无排版问题 +- [ ] 外链已移至「阅读原文」 +- [ ] 摘要和封面已设置 +``` diff --git a/account/admin/skills/xiaohongshu-creator/.openakita-i18n.json b/account/admin/skills/xiaohongshu-creator/.openakita-i18n.json new file mode 100644 index 0000000..7ba91dc --- /dev/null +++ b/account/admin/skills/xiaohongshu-creator/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "小红书内容创作", + "description": "生成符合小红书平台调性的笔记内容,包括标题、正文、话题标签和配图建议,支持种草、测评、教程、生活分享等多种内容类型。" + } +} diff --git a/account/admin/skills/xiaohongshu-creator/SKILL.md b/account/admin/skills/xiaohongshu-creator/SKILL.md new file mode 100644 index 0000000..827bf3d --- /dev/null +++ b/account/admin/skills/xiaohongshu-creator/SKILL.md @@ -0,0 +1,315 @@ +--- +name: openakita/skills@xiaohongshu-creator +description: Create engaging Xiaohongshu (RED/小红书) content including titles, body text, hashtags, and image style recommendations. Supports multiple content types such as product reviews, tutorials, lifestyle sharing, and shopping guides with platform-specific optimization. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# 小红书内容创作助手 + +专为小红书平台打造的内容创作技能,帮助你生成符合平台调性的高质量笔记,涵盖标题、正文、话题标签和配图建议。 + +## 适用场景 + +- 撰写种草笔记(好物推荐、购物分享) +- 撰写产品测评笔记 +- 撰写教程类笔记(美妆、穿搭、美食、DIY) +- 撰写生活分享笔记(旅行、日常、打卡) +- 品牌合作内容创作 +- 小红书账号运营内容规划 +- 批量生成笔记框架 + +## 核心创作规范 + +### 一、标题规则 + +标题是笔记的第一印象,直接决定点击率。 + +**硬性要求:** +- 字数限制:**不超过 20 个字符** +- Emoji 数量:**1-2 个**,放在标题开头或结尾 +- 禁止使用:感叹号堆叠(`!!!`)、全大写字母 + +**钩子元素(至少使用 1 种):** + +| 钩子类型 | 说明 | 示例 | +|----------|------|------| +| 数字法 | 用数字制造具体感 | `3步搞定通勤妆🌟` | +| 反差法 | 制造意外感 | `月薪3K穿出3W的感觉✨` | +| 痛点法 | 直击目标人群痛点 | `黄皮亲妈色号合集🎨` | +| 悬念法 | 引发好奇心 | `这个习惯让我瘦了20斤💪` | +| 对比法 | 前后/AB对比 | `早C晚A一个月的变化🔥` | +| 权威法 | 借势专业背书 | `皮肤科医生推荐的面霜💊` | +| 场景法 | 具体使用场景 | `约会前30分钟急救妆容💄` | +| 共鸣法 | 引发情感共鸣 | `打工人的高效早餐方案☀️` | + +**标题模板:** +``` +[数字] + [核心关键词] + [利益点] + [emoji] +[身份标签] + [动作] + [结果] + [emoji] +[场景] + [解决方案] + [emoji] +``` + +### 二、正文结构 + +正文长度控制在 **300-500 字符**,遵循四段式结构: + +``` +🔥 Hook(开头钩子) —— 1-2 句,抓住注意力 +📝 Core(核心内容) —— 主体信息,有价值的干货 +📌 Summary(总结) —— 精炼要点 +👉 CTA(行动号召) —— 引导互动 +``` + +**Hook 写法:** +- 提问式:`你们有没有这种烦恼?` +- 共鸣式:`每个打工人都需要这个!` +- 悬念式:`用了三年终于找到了最好用的...` +- 成果式:`坚持30天,效果太惊人了` + +**Core 写法要点:** +- 使用 emoji 分点(📍🔸💡等)替代纯文字列表 +- 每个要点控制在 1-2 行 +- 穿插个人体验和感受(增加真实感) +- 重要信息加【】或「」标注 +- 适当使用换行,避免大段文字 + +**CTA 常用句式:** +- `觉得有用的话记得点赞收藏哦~` +- `你们还想看什么类型的分享?评论区告诉我` +- `有同款的姐妹举个手🙋‍♀️` +- `关注我,持续分享[领域]干货` + +### 三、话题标签规则 + +每篇笔记配 **8 个话题标签**,按以下比例分配: + +| 类别 | 数量 | 说明 | 示例 | +|------|------|------|------| +| 核心词 | 2 个 | 笔记主题精准关键词 | `#面膜推荐` `#保湿面膜` | +| 品类词 | 2 个 | 所属品类/领域 | `#护肤` `#美妆好物` | +| 场景词 | 2 个 | 使用场景/人群 | `#学生党护肤` `#换季护肤` | +| 热门词 | 2 个 | 平台热门话题 | `#好物分享` `#我的爱用物` | + +**选择原则:** +- 优先选择搜索量大但竞争适中的标签 +- 避免过于宽泛的标签(如 `#生活`) +- 包含长尾关键词提升搜索曝光 +- 关注平台当前热门话题榜 + +### 四、配图风格建议 + +小红书是视觉驱动平台,封面决定 80% 的点击率。 + +**10 种推荐视觉风格:** + +| 编号 | 风格 | 适用类型 | 要点 | +|------|------|---------|------| +| 1 | 对比拼图 | 测评/效果展示 | 左右或上下对比,标注差异 | +| 2 | 清单图 | 好物合集/推荐 | 白底九宫格产品陈列 | +| 3 | 教程步骤图 | 教程类 | 编号标注步骤,清晰易跟 | +| 4 | 文字封面 | 干货分享 | 大字标题+简洁背景色 | +| 5 | 场景氛围图 | 生活分享/穿搭 | 自然光,生活感强 | +| 6 | 数据图表 | 测评/科普 | 简化数据可视化 | +| 7 | 手绘/插画风 | 知识科普 | 可爱风格信息图 | +| 8 | Vlog截图 | 日常分享 | 视频关键帧+文字标注 | +| 9 | 实拍特写 | 产品种草 | 高清细节,突出质感 | +| 10 | Ins风简约 | 穿搭/家居 | 低饱和度,高级感 | + +**封面设计通用原则:** +- 尺寸比例:**3:4**(1080×1440px)最佳 +- 文字不超过封面面积的 **20%** +- 核心信息放在画面上半部分(feed 流裁剪安全区) +- 色彩鲜明、对比度高 +- 避免过度 P 图,保持真实感 + +## 内容类型工作流 + +### 工作流一:种草笔记 + +``` +输入 → 产品名称、品类、价格、目标人群 + ↓ +Step 1: 生成 3 个标题方案(痛点法/数字法/场景法各一) + ↓ +Step 2: 撰写正文 + - Hook:个人使用感受/发现契机 + - Core:产品亮点(3-5个)、使用方法、适合人群 + - Summary:一句话总结推荐理由 + - CTA:引导收藏和讨论 + ↓ +Step 3: 生成 8 个话题标签 + ↓ +Step 4: 封面建议(推荐风格 9 实拍特写 或 风格 2 清单图) + ↓ +输出 → 完整笔记(可直接发布) +``` + +### 工作流二:测评笔记 + +``` +输入 → 产品列表(2-5 个)、测评维度 + ↓ +Step 1: 标题使用对比法或数字法 + ↓ +Step 2: 撰写正文 + - Hook:测评动机/痛点引入 + - Core:逐项对比(成分/价格/使用感/性价比) + - Summary:各产品评分或排名 + - CTA:`你们用过哪个?评论区聊聊` + ↓ +Step 3: 话题标签(增加品牌词标签) + ↓ +Step 4: 封面建议(推荐风格 1 对比拼图 或 风格 6 数据图表) + ↓ +输出 → 完整测评笔记 +``` + +### 工作流三:教程笔记 + +``` +输入 → 教程主题、难度、目标人群 + ↓ +Step 1: 标题使用数字法(`X步学会...`) + ↓ +Step 2: 撰写正文 + - Hook:学会后的效果/价值 + - Core:分步骤讲解(每步 1-2 句) + - Summary:关键注意事项 + - CTA:`学会的打个✅` + ↓ +Step 3: 话题标签(增加 `#教程` `#手把手教学` 等) + ↓ +Step 4: 封面建议(推荐风格 3 步骤图 或 风格 4 文字封面) + ↓ +输出 → 完整教程笔记 + 多图建议(每步一张图) +``` + +### 工作流四:生活分享笔记 + +``` +输入 → 分享主题、场景、情绪基调 + ↓ +Step 1: 标题使用共鸣法或场景法 + ↓ +Step 2: 撰写正文 + - Hook:故事开头/情感切入 + - Core:分享细节、个人感受、实用信息 + - Summary:感悟或建议 + - CTA:`你们有类似的经历吗?` + ↓ +Step 3: 话题标签(增加情感/生活方式标签) + ↓ +Step 4: 封面建议(推荐风格 5 场景氛围图 或 风格 8 Vlog截图) + ↓ +输出 → 完整分享笔记 +``` + +## 完整示例 + +### 示例:护肤种草笔记 + +**用户输入:** `帮我写一篇关于珂润面霜的种草笔记,目标人群是敏感肌学生党` + +**输出:** + +**标题方案:** +1. `敏感肌救星!这罐面霜用了3年回购🧴` +2. `学生党百元面霜天花板💰` +3. `换季烂脸?皮肤科医生同款面霜🏥` + +**正文(选用标题1):** + +``` +姐妹们!!敏感肌的福音真的来了 + +作为一个烂脸三年的敏感肌 终于找到了真正好用的面霜 + +📍珂润面霜使用感受: +🔸质地:乳白色霜状 不厚重 好推开 +🔸保湿:神经酰胺成分 修护屏障一绝 +🔸温和度:无香精无酒精 敏感期也能用 +🔸性价比:百元出头 学生党无压力 + +💡使用tips: +1️⃣ 先乳后霜 吸收更好 +2️⃣ 换季加量使用 厚涂当睡眠面膜 +3️⃣ 搭配同系列化妆水效果翻倍 + +用了整整三年 每次回购都是囤两罐的节奏 +敏感肌姐妹真的可以闭眼入! + +觉得有用记得收藏💕 还想看什么评论区告诉我~ +``` + +**话题标签:** +`#珂润面霜` `#敏感肌护肤` `#学生党护肤` `#平价面霜推荐` `#神经酰胺` `#换季护肤` `#好物分享` `#护肤干货` + +**封面建议:** 风格 9(实拍特写),自然光下拍摄面霜质地细节图,辅以手写标注关键成分。 + +## 高级技巧 + +### 发布时间建议 + +| 时段 | 说明 | +|------|------| +| 7:00-9:00 | 通勤高峰,碎片化浏览 | +| 12:00-14:00 | 午休时间,浏览高峰 | +| 18:00-20:00 | 下班后休闲浏览 | +| 21:00-23:00 | 睡前黄金时段,互动率最高 | + +### SEO 优化 + +- 标题和正文前 50 字包含核心关键词 +- 使用平台搜索下拉词作为参考 +- 正文自然融入 3-5 个相关关键词(避免堆砌) +- 评论区补充关键词(自评增加曝光) + +### 互动率提升 + +- 正文中设置互动问题(`你们觉得呢?`) +- 结尾提供选择题(`A还是B?评论区投票`) +- 24 小时内回复所有评论 +- 置顶评论放重要补充信息 + +## 常见误区 + +| 误区 | 正确做法 | +|------|---------| +| 标题过长(超20字) | 精炼到 20 字以内,信息密度优先 | +| 正文大段不分行 | 每 2-3 行空一行,用 emoji 分隔 | +| 标签太宽泛 | 组合使用泛词+精准词+长尾词 | +| 封面文字太多 | 封面突出视觉冲击,详细信息放正文 | +| 纯广告无真实感 | 加入个人体验和真实细节 | +| 内容同质化严重 | 找到独特切入角度(身份/场景/反差) | +| 忽略评论区运营 | 主动回复并引导二次互动 | + +## 输出格式规范 + +每次生成内容时,严格按以下格式输出: + +```markdown +## 📝 小红书笔记 + +### 标题方案 +1. [方案一] +2. [方案二] +3. [方案三] + +### 正文 +[完整正文内容] + +### 话题标签 +[8个标签] + +### 封面建议 +- 推荐风格:[编号+名称] +- 具体建议:[详细说明] +- 配色方案:[色系建议] + +### 发布建议 +- 推荐时段:[具体时间] +- 注意事项:[补充说明] +``` diff --git a/account/admin/skills/xlsx/LICENSE.txt b/account/admin/skills/xlsx/LICENSE.txt new file mode 100644 index 0000000..c55ab42 --- /dev/null +++ b/account/admin/skills/xlsx/LICENSE.txt @@ -0,0 +1,30 @@ +© 2025 Anthropic, PBC. All rights reserved. + +LICENSE: Use of these materials (including all code, prompts, assets, files, +and other components of this Skill) is governed by your agreement with +Anthropic regarding use of Anthropic's services. If no separate agreement +exists, use is governed by Anthropic's Consumer Terms of Service or +Commercial Terms of Service, as applicable: +https://www.anthropic.com/legal/consumer-terms +https://www.anthropic.com/legal/commercial-terms +Your applicable agreement is referred to as the "Agreement." "Services" are +as defined in the Agreement. + +ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the +contrary, users may not: + +- Extract these materials from the Services or retain copies of these + materials outside the Services +- Reproduce or copy these materials, except for temporary copies created + automatically during authorized use of the Services +- Create derivative works based on these materials +- Distribute, sublicense, or transfer these materials to any third party +- Make, offer to sell, sell, or import any inventions embodied in these + materials +- Reverse engineer, decompile, or disassemble these materials + +The receipt, viewing, or possession of these materials does not convey or +imply any license or right beyond those expressly granted above. + +Anthropic retains all right, title, and interest in these materials, +including all copyrights, patents, and other intellectual property rights. diff --git a/account/admin/skills/xlsx/SKILL.md b/account/admin/skills/xlsx/SKILL.md new file mode 100644 index 0000000..093fc6c --- /dev/null +++ b/account/admin/skills/xlsx/SKILL.md @@ -0,0 +1,292 @@ +--- +name: openakita/skills@xlsx +description: "Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved." +license: Proprietary. LICENSE.txt has complete terms +--- + +# Requirements for Outputs + +## All Excel files + +### Professional Font +- Use a consistent, professional font (e.g., Arial, Times New Roman) for all deliverables unless otherwise instructed by the user + +### Zero Formula Errors +- Every Excel model MUST be delivered with ZERO formula errors (#REF!, #DIV/0!, #VALUE!, #N/A, #NAME?) + +### Preserve Existing Templates (when updating templates) +- Study and EXACTLY match existing format, style, and conventions when modifying files +- Never impose standardized formatting on files with established patterns +- Existing template conventions ALWAYS override these guidelines + +## Financial models + +### Color Coding Standards +Unless otherwise stated by the user or existing template + +#### Industry-Standard Color Conventions +- **Blue text (RGB: 0,0,255)**: Hardcoded inputs, and numbers users will change for scenarios +- **Black text (RGB: 0,0,0)**: ALL formulas and calculations +- **Green text (RGB: 0,128,0)**: Links pulling from other worksheets within same workbook +- **Red text (RGB: 255,0,0)**: External links to other files +- **Yellow background (RGB: 255,255,0)**: Key assumptions needing attention or cells that need to be updated + +### Number Formatting Standards + +#### Required Format Rules +- **Years**: Format as text strings (e.g., "2024" not "2,024") +- **Currency**: Use $#,##0 format; ALWAYS specify units in headers ("Revenue ($mm)") +- **Zeros**: Use number formatting to make all zeros "-", including percentages (e.g., "$#,##0;($#,##0);-") +- **Percentages**: Default to 0.0% format (one decimal) +- **Multiples**: Format as 0.0x for valuation multiples (EV/EBITDA, P/E) +- **Negative numbers**: Use parentheses (123) not minus -123 + +### Formula Construction Rules + +#### Assumptions Placement +- Place ALL assumptions (growth rates, margins, multiples, etc.) in separate assumption cells +- Use cell references instead of hardcoded values in formulas +- Example: Use =B5*(1+$B$6) instead of =B5*1.05 + +#### Formula Error Prevention +- Verify all cell references are correct +- Check for off-by-one errors in ranges +- Ensure consistent formulas across all projection periods +- Test with edge cases (zero values, negative numbers) +- Verify no unintended circular references + +#### Documentation Requirements for Hardcodes +- Comment or in cells beside (if end of table). Format: "Source: [System/Document], [Date], [Specific Reference], [URL if applicable]" +- Examples: + - "Source: Company 10-K, FY2024, Page 45, Revenue Note, [SEC EDGAR URL]" + - "Source: Company 10-Q, Q2 2025, Exhibit 99.1, [SEC EDGAR URL]" + - "Source: Bloomberg Terminal, 8/15/2025, AAPL US Equity" + - "Source: FactSet, 8/20/2025, Consensus Estimates Screen" + +# XLSX creation, editing, and analysis + +## Overview + +A user may ask you to create, edit, or analyze the contents of an .xlsx file. You have different tools and workflows available for different tasks. + +## Important Requirements + +**LibreOffice Required for Formula Recalculation**: You can assume LibreOffice is installed for recalculating formula values using the `scripts/recalc.py` script. The script automatically configures LibreOffice on first run, including in sandboxed environments where Unix sockets are restricted (handled by `scripts/office/soffice.py`) + +## Reading and analyzing data + +### Data analysis with pandas +For data analysis, visualization, and basic operations, use **pandas** which provides powerful data manipulation capabilities: + +```python +import pandas as pd + +# Read Excel +df = pd.read_excel('file.xlsx') # Default: first sheet +all_sheets = pd.read_excel('file.xlsx', sheet_name=None) # All sheets as dict + +# Analyze +df.head() # Preview data +df.info() # Column info +df.describe() # Statistics + +# Write Excel +df.to_excel('output.xlsx', index=False) +``` + +## Excel File Workflows + +## CRITICAL: Use Formulas, Not Hardcoded Values + +**Always use Excel formulas instead of calculating values in Python and hardcoding them.** This ensures the spreadsheet remains dynamic and updateable. + +### ❌ WRONG - Hardcoding Calculated Values +```python +# Bad: Calculating in Python and hardcoding result +total = df['Sales'].sum() +sheet['B10'] = total # Hardcodes 5000 + +# Bad: Computing growth rate in Python +growth = (df.iloc[-1]['Revenue'] - df.iloc[0]['Revenue']) / df.iloc[0]['Revenue'] +sheet['C5'] = growth # Hardcodes 0.15 + +# Bad: Python calculation for average +avg = sum(values) / len(values) +sheet['D20'] = avg # Hardcodes 42.5 +``` + +### ✅ CORRECT - Using Excel Formulas +```python +# Good: Let Excel calculate the sum +sheet['B10'] = '=SUM(B2:B9)' + +# Good: Growth rate as Excel formula +sheet['C5'] = '=(C4-C2)/C2' + +# Good: Average using Excel function +sheet['D20'] = '=AVERAGE(D2:D19)' +``` + +This applies to ALL calculations - totals, percentages, ratios, differences, etc. The spreadsheet should be able to recalculate when source data changes. + +## Common Workflow +1. **Choose tool**: pandas for data, openpyxl for formulas/formatting +2. **Create/Load**: Create new workbook or load existing file +3. **Modify**: Add/edit data, formulas, and formatting +4. **Save**: Write to file +5. **Recalculate formulas (MANDATORY IF USING FORMULAS)**: Use the scripts/recalc.py script + ```bash + python scripts/recalc.py output.xlsx + ``` +6. **Verify and fix any errors**: + - The script returns JSON with error details + - If `status` is `errors_found`, check `error_summary` for specific error types and locations + - Fix the identified errors and recalculate again + - Common errors to fix: + - `#REF!`: Invalid cell references + - `#DIV/0!`: Division by zero + - `#VALUE!`: Wrong data type in formula + - `#NAME?`: Unrecognized formula name + +### Creating new Excel files + +```python +# Using openpyxl for formulas and formatting +from openpyxl import Workbook +from openpyxl.styles import Font, PatternFill, Alignment + +wb = Workbook() +sheet = wb.active + +# Add data +sheet['A1'] = 'Hello' +sheet['B1'] = 'World' +sheet.append(['Row', 'of', 'data']) + +# Add formula +sheet['B2'] = '=SUM(A1:A10)' + +# Formatting +sheet['A1'].font = Font(bold=True, color='FF0000') +sheet['A1'].fill = PatternFill('solid', start_color='FFFF00') +sheet['A1'].alignment = Alignment(horizontal='center') + +# Column width +sheet.column_dimensions['A'].width = 20 + +wb.save('output.xlsx') +``` + +### Editing existing Excel files + +```python +# Using openpyxl to preserve formulas and formatting +from openpyxl import load_workbook + +# Load existing file +wb = load_workbook('existing.xlsx') +sheet = wb.active # or wb['SheetName'] for specific sheet + +# Working with multiple sheets +for sheet_name in wb.sheetnames: + sheet = wb[sheet_name] + print(f"Sheet: {sheet_name}") + +# Modify cells +sheet['A1'] = 'New Value' +sheet.insert_rows(2) # Insert row at position 2 +sheet.delete_cols(3) # Delete column 3 + +# Add new sheet +new_sheet = wb.create_sheet('NewSheet') +new_sheet['A1'] = 'Data' + +wb.save('modified.xlsx') +``` + +## Recalculating formulas + +Excel files created or modified by openpyxl contain formulas as strings but not calculated values. Use the provided `scripts/recalc.py` script to recalculate formulas: + +```bash +python scripts/recalc.py <excel_file> [timeout_seconds] +``` + +Example: +```bash +python scripts/recalc.py output.xlsx 30 +``` + +The script: +- Automatically sets up LibreOffice macro on first run +- Recalculates all formulas in all sheets +- Scans ALL cells for Excel errors (#REF!, #DIV/0!, etc.) +- Returns JSON with detailed error locations and counts +- Works on both Linux and macOS + +## Formula Verification Checklist + +Quick checks to ensure formulas work correctly: + +### Essential Verification +- [ ] **Test 2-3 sample references**: Verify they pull correct values before building full model +- [ ] **Column mapping**: Confirm Excel columns match (e.g., column 64 = BL, not BK) +- [ ] **Row offset**: Remember Excel rows are 1-indexed (DataFrame row 5 = Excel row 6) + +### Common Pitfalls +- [ ] **NaN handling**: Check for null values with `pd.notna()` +- [ ] **Far-right columns**: FY data often in columns 50+ +- [ ] **Multiple matches**: Search all occurrences, not just first +- [ ] **Division by zero**: Check denominators before using `/` in formulas (#DIV/0!) +- [ ] **Wrong references**: Verify all cell references point to intended cells (#REF!) +- [ ] **Cross-sheet references**: Use correct format (Sheet1!A1) for linking sheets + +### Formula Testing Strategy +- [ ] **Start small**: Test formulas on 2-3 cells before applying broadly +- [ ] **Verify dependencies**: Check all cells referenced in formulas exist +- [ ] **Test edge cases**: Include zero, negative, and very large values + +### Interpreting scripts/recalc.py Output +The script returns JSON with error details: +```json +{ + "status": "success", // or "errors_found" + "total_errors": 0, // Total error count + "total_formulas": 42, // Number of formulas in file + "error_summary": { // Only present if errors found + "#REF!": { + "count": 2, + "locations": ["Sheet1!B5", "Sheet1!C10"] + } + } +} +``` + +## Best Practices + +### Library Selection +- **pandas**: Best for data analysis, bulk operations, and simple data export +- **openpyxl**: Best for complex formatting, formulas, and Excel-specific features + +### Working with openpyxl +- Cell indices are 1-based (row=1, column=1 refers to cell A1) +- Use `data_only=True` to read calculated values: `load_workbook('file.xlsx', data_only=True)` +- **Warning**: If opened with `data_only=True` and saved, formulas are replaced with values and permanently lost +- For large files: Use `read_only=True` for reading or `write_only=True` for writing +- Formulas are preserved but not evaluated - use scripts/recalc.py to update values + +### Working with pandas +- Specify data types to avoid inference issues: `pd.read_excel('file.xlsx', dtype={'id': str})` +- For large files, read specific columns: `pd.read_excel('file.xlsx', usecols=['A', 'C', 'E'])` +- Handle dates properly: `pd.read_excel('file.xlsx', parse_dates=['date_column'])` + +## Code Style Guidelines +**IMPORTANT**: When generating Python code for Excel operations: +- Write minimal, concise Python code without unnecessary comments +- Avoid verbose variable names and redundant operations +- Avoid unnecessary print statements + +**For Excel files themselves**: +- Add comments to cells with complex formulas or important assumptions +- Document data sources for hardcoded values +- Include notes for key calculations and model sections \ No newline at end of file diff --git a/account/admin/skills/xlsx/recalc.py b/account/admin/skills/xlsx/recalc.py new file mode 100644 index 0000000..102e157 --- /dev/null +++ b/account/admin/skills/xlsx/recalc.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +""" +Excel Formula Recalculation Script +Recalculates all formulas in an Excel file using LibreOffice +""" + +import json +import sys +import subprocess +import os +import platform +from pathlib import Path +from openpyxl import load_workbook + + +def setup_libreoffice_macro(): + """Setup LibreOffice macro for recalculation if not already configured""" + if platform.system() == 'Darwin': + macro_dir = os.path.expanduser('~/Library/Application Support/LibreOffice/4/user/basic/Standard') + else: + macro_dir = os.path.expanduser('~/.config/libreoffice/4/user/basic/Standard') + + macro_file = os.path.join(macro_dir, 'Module1.xba') + + if os.path.exists(macro_file): + with open(macro_file, 'r') as f: + if 'RecalculateAndSave' in f.read(): + return True + + if not os.path.exists(macro_dir): + subprocess.run(['soffice', '--headless', '--terminate_after_init'], + capture_output=True, timeout=10) + os.makedirs(macro_dir, exist_ok=True) + + macro_content = '''<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> +<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic"> + Sub RecalculateAndSave() + ThisComponent.calculateAll() + ThisComponent.store() + ThisComponent.close(True) + End Sub +</script:module>''' + + try: + with open(macro_file, 'w') as f: + f.write(macro_content) + return True + except Exception: + return False + + +def recalc(filename, timeout=30): + """ + Recalculate formulas in Excel file and report any errors + + Args: + filename: Path to Excel file + timeout: Maximum time to wait for recalculation (seconds) + + Returns: + dict with error locations and counts + """ + if not Path(filename).exists(): + return {'error': f'File {filename} does not exist'} + + abs_path = str(Path(filename).absolute()) + + if not setup_libreoffice_macro(): + return {'error': 'Failed to setup LibreOffice macro'} + + cmd = [ + 'soffice', '--headless', '--norestore', + 'vnd.sun.star.script:Standard.Module1.RecalculateAndSave?language=Basic&location=application', + abs_path + ] + + # Handle timeout command differences between Linux and macOS + if platform.system() != 'Windows': + timeout_cmd = 'timeout' if platform.system() == 'Linux' else None + if platform.system() == 'Darwin': + # Check if gtimeout is available on macOS + try: + subprocess.run(['gtimeout', '--version'], capture_output=True, timeout=1, check=False) + timeout_cmd = 'gtimeout' + except (FileNotFoundError, subprocess.TimeoutExpired): + pass + + if timeout_cmd: + cmd = [timeout_cmd, str(timeout)] + cmd + + result = subprocess.run(cmd, capture_output=True, text=True) + + if result.returncode != 0 and result.returncode != 124: # 124 is timeout exit code + error_msg = result.stderr or 'Unknown error during recalculation' + if 'Module1' in error_msg or 'RecalculateAndSave' not in error_msg: + return {'error': 'LibreOffice macro not configured properly'} + else: + return {'error': error_msg} + + # Check for Excel errors in the recalculated file - scan ALL cells + try: + wb = load_workbook(filename, data_only=True) + + excel_errors = ['#VALUE!', '#DIV/0!', '#REF!', '#NAME?', '#NULL!', '#NUM!', '#N/A'] + error_details = {err: [] for err in excel_errors} + total_errors = 0 + + for sheet_name in wb.sheetnames: + ws = wb[sheet_name] + # Check ALL rows and columns - no limits + for row in ws.iter_rows(): + for cell in row: + if cell.value is not None and isinstance(cell.value, str): + for err in excel_errors: + if err in cell.value: + location = f"{sheet_name}!{cell.coordinate}" + error_details[err].append(location) + total_errors += 1 + break + + wb.close() + + # Build result summary + result = { + 'status': 'success' if total_errors == 0 else 'errors_found', + 'total_errors': total_errors, + 'error_summary': {} + } + + # Add non-empty error categories + for err_type, locations in error_details.items(): + if locations: + result['error_summary'][err_type] = { + 'count': len(locations), + 'locations': locations[:20] # Show up to 20 locations + } + + # Add formula count for context - also check ALL cells + wb_formulas = load_workbook(filename, data_only=False) + formula_count = 0 + for sheet_name in wb_formulas.sheetnames: + ws = wb_formulas[sheet_name] + for row in ws.iter_rows(): + for cell in row: + if cell.value and isinstance(cell.value, str) and cell.value.startswith('='): + formula_count += 1 + wb_formulas.close() + + result['total_formulas'] = formula_count + + return result + + except Exception as e: + return {'error': str(e)} + + +def main(): + if len(sys.argv) < 2: + print("Usage: python recalc.py <excel_file> [timeout_seconds]") + print("\nRecalculates all formulas in an Excel file using LibreOffice") + print("\nReturns JSON with error details:") + print(" - status: 'success' or 'errors_found'") + print(" - total_errors: Total number of Excel errors found") + print(" - total_formulas: Number of formulas in the file") + print(" - error_summary: Breakdown by error type with locations") + print(" - #VALUE!, #DIV/0!, #REF!, #NAME?, #NULL!, #NUM!, #N/A") + sys.exit(1) + + filename = sys.argv[1] + timeout = int(sys.argv[2]) if len(sys.argv) > 2 else 30 + + result = recalc(filename, timeout) + print(json.dumps(result, indent=2)) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/account/admin/skills/xlsx/scripts/office/helpers/__init__.py b/account/admin/skills/xlsx/scripts/office/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account/admin/skills/xlsx/scripts/office/helpers/merge_runs.py b/account/admin/skills/xlsx/scripts/office/helpers/merge_runs.py new file mode 100644 index 0000000..ad7c25e --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/helpers/merge_runs.py @@ -0,0 +1,199 @@ +"""Merge adjacent runs with identical formatting in DOCX. + +Merges adjacent <w:r> elements that have identical <w:rPr> properties. +Works on runs in paragraphs and inside tracked changes (<w:ins>, <w:del>). + +Also: +- Removes rsid attributes from runs (revision metadata that doesn't affect rendering) +- Removes proofErr elements (spell/grammar markers that block merging) +""" + +from pathlib import Path + +import defusedxml.minidom + + +def merge_runs(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + _remove_elements(root, "proofErr") + _strip_run_rsid_attrs(root) + + containers = {run.parentNode for run in _find_elements(root, "r")} + + merge_count = 0 + for container in containers: + merge_count += _merge_runs_in(container) + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Merged {merge_count} runs" + + except Exception as e: + return 0, f"Error: {e}" + + + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def _get_child(parent, tag: str): + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + return child + return None + + +def _get_children(parent, tag: str) -> list: + results = [] + for child in parent.childNodes: + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(child) + return results + + +def _is_adjacent(elem1, elem2) -> bool: + node = elem1.nextSibling + while node: + if node == elem2: + return True + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + return False + + + + +def _remove_elements(root, tag: str): + for elem in _find_elements(root, tag): + if elem.parentNode: + elem.parentNode.removeChild(elem) + + +def _strip_run_rsid_attrs(root): + for run in _find_elements(root, "r"): + for attr in list(run.attributes.values()): + if "rsid" in attr.name.lower(): + run.removeAttribute(attr.name) + + + + +def _merge_runs_in(container) -> int: + merge_count = 0 + run = _first_child_run(container) + + while run: + while True: + next_elem = _next_element_sibling(run) + if next_elem and _is_run(next_elem) and _can_merge(run, next_elem): + _merge_run_content(run, next_elem) + container.removeChild(next_elem) + merge_count += 1 + else: + break + + _consolidate_text(run) + run = _next_sibling_run(run) + + return merge_count + + +def _first_child_run(container): + for child in container.childNodes: + if child.nodeType == child.ELEMENT_NODE and _is_run(child): + return child + return None + + +def _next_element_sibling(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + return sibling + sibling = sibling.nextSibling + return None + + +def _next_sibling_run(node): + sibling = node.nextSibling + while sibling: + if sibling.nodeType == sibling.ELEMENT_NODE: + if _is_run(sibling): + return sibling + sibling = sibling.nextSibling + return None + + +def _is_run(node) -> bool: + name = node.localName or node.tagName + return name == "r" or name.endswith(":r") + + +def _can_merge(run1, run2) -> bool: + rpr1 = _get_child(run1, "rPr") + rpr2 = _get_child(run2, "rPr") + + if (rpr1 is None) != (rpr2 is None): + return False + if rpr1 is None: + return True + return rpr1.toxml() == rpr2.toxml() + + +def _merge_run_content(target, source): + for child in list(source.childNodes): + if child.nodeType == child.ELEMENT_NODE: + name = child.localName or child.tagName + if name != "rPr" and not name.endswith(":rPr"): + target.appendChild(child) + + +def _consolidate_text(run): + t_elements = _get_children(run, "t") + + for i in range(len(t_elements) - 1, 0, -1): + curr, prev = t_elements[i], t_elements[i - 1] + + if _is_adjacent(prev, curr): + prev_text = prev.firstChild.data if prev.firstChild else "" + curr_text = curr.firstChild.data if curr.firstChild else "" + merged = prev_text + curr_text + + if prev.firstChild: + prev.firstChild.data = merged + else: + prev.appendChild(run.ownerDocument.createTextNode(merged)) + + if merged.startswith(" ") or merged.endswith(" "): + prev.setAttribute("xml:space", "preserve") + elif prev.hasAttribute("xml:space"): + prev.removeAttribute("xml:space") + + run.removeChild(curr) diff --git a/account/admin/skills/xlsx/scripts/office/helpers/simplify_redlines.py b/account/admin/skills/xlsx/scripts/office/helpers/simplify_redlines.py new file mode 100644 index 0000000..db963bb --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/helpers/simplify_redlines.py @@ -0,0 +1,197 @@ +"""Simplify tracked changes by merging adjacent w:ins or w:del elements. + +Merges adjacent <w:ins> elements from the same author into a single element. +Same for <w:del> elements. This makes heavily-redlined documents easier to +work with by reducing the number of tracked change wrappers. + +Rules: +- Only merges w:ins with w:ins, w:del with w:del (same element type) +- Only merges if same author (ignores timestamp differences) +- Only merges if truly adjacent (only whitespace between them) +""" + +import xml.etree.ElementTree as ET +import zipfile +from pathlib import Path + +import defusedxml.minidom + +WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + + +def simplify_redlines(input_dir: str) -> tuple[int, str]: + doc_xml = Path(input_dir) / "word" / "document.xml" + + if not doc_xml.exists(): + return 0, f"Error: {doc_xml} not found" + + try: + dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8")) + root = dom.documentElement + + merge_count = 0 + + containers = _find_elements(root, "p") + _find_elements(root, "tc") + + for container in containers: + merge_count += _merge_tracked_changes_in(container, "ins") + merge_count += _merge_tracked_changes_in(container, "del") + + doc_xml.write_bytes(dom.toxml(encoding="UTF-8")) + return merge_count, f"Simplified {merge_count} tracked changes" + + except Exception as e: + return 0, f"Error: {e}" + + +def _merge_tracked_changes_in(container, tag: str) -> int: + merge_count = 0 + + tracked = [ + child + for child in container.childNodes + if child.nodeType == child.ELEMENT_NODE and _is_element(child, tag) + ] + + if len(tracked) < 2: + return 0 + + i = 0 + while i < len(tracked) - 1: + curr = tracked[i] + next_elem = tracked[i + 1] + + if _can_merge_tracked(curr, next_elem): + _merge_tracked_content(curr, next_elem) + container.removeChild(next_elem) + tracked.pop(i + 1) + merge_count += 1 + else: + i += 1 + + return merge_count + + +def _is_element(node, tag: str) -> bool: + name = node.localName or node.tagName + return name == tag or name.endswith(f":{tag}") + + +def _get_author(elem) -> str: + author = elem.getAttribute("w:author") + if not author: + for attr in elem.attributes.values(): + if attr.localName == "author" or attr.name.endswith(":author"): + return attr.value + return author + + +def _can_merge_tracked(elem1, elem2) -> bool: + if _get_author(elem1) != _get_author(elem2): + return False + + node = elem1.nextSibling + while node and node != elem2: + if node.nodeType == node.ELEMENT_NODE: + return False + if node.nodeType == node.TEXT_NODE and node.data.strip(): + return False + node = node.nextSibling + + return True + + +def _merge_tracked_content(target, source): + while source.firstChild: + child = source.firstChild + source.removeChild(child) + target.appendChild(child) + + +def _find_elements(root, tag: str) -> list: + results = [] + + def traverse(node): + if node.nodeType == node.ELEMENT_NODE: + name = node.localName or node.tagName + if name == tag or name.endswith(f":{tag}"): + results.append(node) + for child in node.childNodes: + traverse(child) + + traverse(root) + return results + + +def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]: + if not doc_xml_path.exists(): + return {} + + try: + tree = ET.parse(doc_xml_path) + root = tree.getroot() + except ET.ParseError: + return {} + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + + return authors + + +def _get_authors_from_docx(docx_path: Path) -> dict[str, int]: + try: + with zipfile.ZipFile(docx_path, "r") as zf: + if "word/document.xml" not in zf.namelist(): + return {} + with zf.open("word/document.xml") as f: + tree = ET.parse(f) + root = tree.getroot() + + namespaces = {"w": WORD_NS} + author_attr = f"{{{WORD_NS}}}author" + + authors: dict[str, int] = {} + for tag in ["ins", "del"]: + for elem in root.findall(f".//w:{tag}", namespaces): + author = elem.get(author_attr) + if author: + authors[author] = authors.get(author, 0) + 1 + return authors + except (zipfile.BadZipFile, ET.ParseError): + return {} + + +def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str: + modified_xml = modified_dir / "word" / "document.xml" + modified_authors = get_tracked_change_authors(modified_xml) + + if not modified_authors: + return default + + original_authors = _get_authors_from_docx(original_docx) + + new_changes: dict[str, int] = {} + for author, count in modified_authors.items(): + original_count = original_authors.get(author, 0) + diff = count - original_count + if diff > 0: + new_changes[author] = diff + + if not new_changes: + return default + + if len(new_changes) == 1: + return next(iter(new_changes)) + + raise ValueError( + f"Multiple authors added new changes: {new_changes}. " + "Cannot infer which author to validate." + ) diff --git a/account/admin/skills/xlsx/scripts/office/pack.py b/account/admin/skills/xlsx/scripts/office/pack.py new file mode 100644 index 0000000..db29ed8 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/pack.py @@ -0,0 +1,159 @@ +"""Pack a directory into a DOCX, PPTX, or XLSX file. + +Validates with auto-repair, condenses XML formatting, and creates the Office file. + +Usage: + python pack.py <input_directory> <output_file> [--original <file>] [--validate true|false] + +Examples: + python pack.py unpacked/ output.docx --original input.docx + python pack.py unpacked/ output.pptx --validate false +""" + +import argparse +import sys +import shutil +import tempfile +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + +def pack( + input_directory: str, + output_file: str, + original_file: str | None = None, + validate: bool = True, + infer_author_func=None, +) -> tuple[None, str]: + input_dir = Path(input_directory) + output_path = Path(output_file) + suffix = output_path.suffix.lower() + + if not input_dir.is_dir(): + return None, f"Error: {input_dir} is not a directory" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file" + + if validate and original_file: + original_path = Path(original_file) + if original_path.exists(): + success, output = _run_validation( + input_dir, original_path, suffix, infer_author_func + ) + if output: + print(output) + if not success: + return None, f"Error: Validation failed for {input_dir}" + + with tempfile.TemporaryDirectory() as temp_dir: + temp_content_dir = Path(temp_dir) / "content" + shutil.copytree(input_dir, temp_content_dir) + + for pattern in ["*.xml", "*.rels"]: + for xml_file in temp_content_dir.rglob(pattern): + _condense_xml(xml_file) + + output_path.parent.mkdir(parents=True, exist_ok=True) + with zipfile.ZipFile(output_path, "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)) + + return None, f"Successfully packed {input_dir} to {output_file}" + + +def _run_validation( + unpacked_dir: Path, + original_file: Path, + suffix: str, + infer_author_func=None, +) -> tuple[bool, str | None]: + output_lines = [] + validators = [] + + if suffix == ".docx": + author = "Claude" + if infer_author_func: + try: + author = infer_author_func(unpacked_dir, original_file) + except ValueError as e: + print(f"Warning: {e} Using default author 'Claude'.", file=sys.stderr) + + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file), + RedliningValidator(unpacked_dir, original_file, author=author), + ] + elif suffix == ".pptx": + validators = [PPTXSchemaValidator(unpacked_dir, original_file)] + + if not validators: + return True, None + + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + output_lines.append(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + output_lines.append("All validations PASSED!") + + return success, "\n".join(output_lines) if output_lines else None + + +def _condense_xml(xml_file: Path) -> None: + try: + with open(xml_file, encoding="utf-8") as f: + dom = defusedxml.minidom.parse(f) + + for element in dom.getElementsByTagName("*"): + if element.tagName.endswith(":t"): + continue + + 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) + + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + except Exception as e: + print(f"ERROR: Failed to parse {xml_file.name}: {e}", file=sys.stderr) + raise + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Pack a directory into a DOCX, PPTX, or XLSX 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( + "--original", + help="Original file for validation comparison", + ) + parser.add_argument( + "--validate", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Run validation with auto-repair (default: true)", + ) + args = parser.parse_args() + + _, message = pack( + args.input_directory, + args.output_file, + original_file=args.original, + validate=args.validate, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd new file mode 100644 index 0000000..6454ef9 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd @@ -0,0 +1,1499 @@ +<?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:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns="http://schemas.openxmlformats.org/drawingml/2006/chart" + xmlns:cdr="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/chart" + elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all"> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + schemaLocation="shared-relationshipReference.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main" + schemaLocation="dml-main.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing" + schemaLocation="dml-chartDrawing.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + schemaLocation="shared-commonSimpleTypes.xsd"/> + <xsd:complexType name="CT_Boolean"> + <xsd:attribute name="val" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_Double"> + <xsd:attribute name="val" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_UnsignedInt"> + <xsd:attribute name="val" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RelId"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <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:complexType name="CT_NumVal"> + <xsd:sequence> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="formatCode" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_NumData"> + <xsd:sequence> + <xsd:element name="formatCode" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pt" type="CT_NumVal" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NumRef"> + <xsd:sequence> + <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/> + <xsd:element name="numCache" type="CT_NumData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NumDataSource"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="numRef" type="CT_NumRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="numLit" type="CT_NumData" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StrVal"> + <xsd:sequence> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_StrData"> + <xsd:sequence> + <xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pt" type="CT_StrVal" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StrRef"> + <xsd:sequence> + <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/> + <xsd:element name="strCache" type="CT_StrData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Tx"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="rich" type="a:CT_TextBody" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TextLanguageID"> + <xsd:attribute name="val" type="s:ST_Lang" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Lvl"> + <xsd:sequence> + <xsd:element name="pt" type="CT_StrVal" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MultiLvlStrData"> + <xsd:sequence> + <xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl" type="CT_Lvl" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MultiLvlStrRef"> + <xsd:sequence> + <xsd:element name="f" type="xsd:string" minOccurs="1" maxOccurs="1"/> + <xsd:element name="multiLvlStrCache" type="CT_MultiLvlStrData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_AxDataSource"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="numRef" type="CT_NumRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="numLit" type="CT_NumData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="strLit" type="CT_StrData" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SerTx"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="strRef" type="CT_StrRef" minOccurs="1" maxOccurs="1"/> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_LayoutTarget"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="inner"/> + <xsd:enumeration value="outer"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LayoutTarget"> + <xsd:attribute name="val" type="ST_LayoutTarget" default="outer"/> + </xsd:complexType> + <xsd:simpleType name="ST_LayoutMode"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="edge"/> + <xsd:enumeration value="factor"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LayoutMode"> + <xsd:attribute name="val" type="ST_LayoutMode" default="factor"/> + </xsd:complexType> + <xsd:complexType name="CT_ManualLayout"> + <xsd:sequence> + <xsd:element name="layoutTarget" type="CT_LayoutTarget" minOccurs="0" maxOccurs="1"/> + <xsd:element name="xMode" type="CT_LayoutMode" minOccurs="0" maxOccurs="1"/> + <xsd:element name="yMode" type="CT_LayoutMode" minOccurs="0" maxOccurs="1"/> + <xsd:element name="wMode" type="CT_LayoutMode" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hMode" type="CT_LayoutMode" minOccurs="0" maxOccurs="1"/> + <xsd:element name="x" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="y" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="w" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="h" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Layout"> + <xsd:sequence> + <xsd:element name="manualLayout" type="CT_ManualLayout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Title"> + <xsd:sequence> + <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_RotX"> + <xsd:restriction base="xsd:byte"> + <xsd:minInclusive value="-90"/> + <xsd:maxInclusive value="90"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_RotX"> + <xsd:attribute name="val" type="ST_RotX" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_HPercent"> + <xsd:union memberTypes="ST_HPercentWithSymbol ST_HPercentUShort"/> + </xsd:simpleType> + <xsd:simpleType name="ST_HPercentWithSymbol"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HPercentUShort"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="5"/> + <xsd:maxInclusive value="500"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_HPercent"> + <xsd:attribute name="val" type="ST_HPercent" default="100%"/> + </xsd:complexType> + <xsd:simpleType name="ST_RotY"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="360"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_RotY"> + <xsd:attribute name="val" type="ST_RotY" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_DepthPercent"> + <xsd:union memberTypes="ST_DepthPercentWithSymbol ST_DepthPercentUShort"/> + </xsd:simpleType> + <xsd:simpleType name="ST_DepthPercentWithSymbol"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DepthPercentUShort"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="20"/> + <xsd:maxInclusive value="2000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DepthPercent"> + <xsd:attribute name="val" type="ST_DepthPercent" default="100%"/> + </xsd:complexType> + <xsd:simpleType name="ST_Perspective"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="240"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Perspective"> + <xsd:attribute name="val" type="ST_Perspective" default="30"/> + </xsd:complexType> + <xsd:complexType name="CT_View3D"> + <xsd:sequence> + <xsd:element name="rotX" type="CT_RotX" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hPercent" type="CT_HPercent" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rotY" type="CT_RotY" minOccurs="0" maxOccurs="1"/> + <xsd:element name="depthPercent" type="CT_DepthPercent" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rAngAx" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="perspective" type="CT_Perspective" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Surface"> + <xsd:sequence> + <xsd:element name="thickness" type="CT_Thickness" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Thickness"> + <xsd:union memberTypes="ST_ThicknessPercent xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_ThicknessPercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="([0-9]+)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Thickness"> + <xsd:attribute name="val" type="ST_Thickness" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DTable"> + <xsd:sequence> + <xsd:element name="showHorzBorder" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showVertBorder" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showOutline" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showKeys" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_GapAmount"> + <xsd:union memberTypes="ST_GapAmountPercent ST_GapAmountUShort"/> + </xsd:simpleType> + <xsd:simpleType name="ST_GapAmountPercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_GapAmountUShort"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="500"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_GapAmount"> + <xsd:attribute name="val" type="ST_GapAmount" default="150%"/> + </xsd:complexType> + <xsd:simpleType name="ST_Overlap"> + <xsd:union memberTypes="ST_OverlapPercent ST_OverlapByte"/> + </xsd:simpleType> + <xsd:simpleType name="ST_OverlapPercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="(-?0*(([0-9])|([1-9][0-9])|100))%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_OverlapByte"> + <xsd:restriction base="xsd:byte"> + <xsd:minInclusive value="-100"/> + <xsd:maxInclusive value="100"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Overlap"> + <xsd:attribute name="val" type="ST_Overlap" default="0%"/> + </xsd:complexType> + <xsd:simpleType name="ST_BubbleScale"> + <xsd:union memberTypes="ST_BubbleScalePercent ST_BubbleScaleUInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_BubbleScalePercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-2][0-9][0-9])|300)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_BubbleScaleUInt"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="300"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_BubbleScale"> + <xsd:attribute name="val" type="ST_BubbleScale" default="100%"/> + </xsd:complexType> + <xsd:simpleType name="ST_SizeRepresents"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="area"/> + <xsd:enumeration value="w"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SizeRepresents"> + <xsd:attribute name="val" type="ST_SizeRepresents" default="area"/> + </xsd:complexType> + <xsd:simpleType name="ST_FirstSliceAng"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="360"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FirstSliceAng"> + <xsd:attribute name="val" type="ST_FirstSliceAng" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_HoleSize"> + <xsd:union memberTypes="ST_HoleSizePercent ST_HoleSizeUByte"/> + </xsd:simpleType> + <xsd:simpleType name="ST_HoleSizePercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*([1-9]|([1-8][0-9])|90)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HoleSizeUByte"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="1"/> + <xsd:maxInclusive value="90"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_HoleSize"> + <xsd:attribute name="val" type="ST_HoleSize" default="10%"/> + </xsd:complexType> + <xsd:simpleType name="ST_SplitType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="cust"/> + <xsd:enumeration value="percent"/> + <xsd:enumeration value="pos"/> + <xsd:enumeration value="val"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SplitType"> + <xsd:attribute name="val" type="ST_SplitType" default="auto"/> + </xsd:complexType> + <xsd:complexType name="CT_CustSplit"> + <xsd:sequence> + <xsd:element name="secondPiePt" type="CT_UnsignedInt" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_SecondPieSize"> + <xsd:union memberTypes="ST_SecondPieSizePercent ST_SecondPieSizeUShort"/> + </xsd:simpleType> + <xsd:simpleType name="ST_SecondPieSizePercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([5-9])|([1-9][0-9])|(1[0-9][0-9])|200)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_SecondPieSizeUShort"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="5"/> + <xsd:maxInclusive value="200"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SecondPieSize"> + <xsd:attribute name="val" type="ST_SecondPieSize" default="75%"/> + </xsd:complexType> + <xsd:complexType name="CT_NumFmt"> + <xsd:attribute name="formatCode" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="sourceLinked" type="xsd:boolean"/> + </xsd:complexType> + <xsd:simpleType name="ST_LblAlgn"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LblAlgn"> + <xsd:attribute name="val" type="ST_LblAlgn" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DLblPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="bestFit"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="inBase"/> + <xsd:enumeration value="inEnd"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="outEnd"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="t"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DLblPos"> + <xsd:attribute name="val" type="ST_DLblPos" use="required"/> + </xsd:complexType> + <xsd:group name="EG_DLblShared"> + <xsd:sequence> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dLblPos" type="CT_DLblPos" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showLegendKey" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showVal" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showCatName" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showSerName" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showPercent" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showBubbleSize" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="separator" type="xsd:string" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:group name="Group_DLbl"> + <xsd:sequence> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_DLblShared" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_DLbl"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:choice> + <xsd:element name="delete" type="CT_Boolean" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="Group_DLbl" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="Group_DLbls"> + <xsd:sequence> + <xsd:group ref="EG_DLblShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="showLeaderLines" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="leaderLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_DLbls"> + <xsd:sequence> + <xsd:element name="dLbl" type="CT_DLbl" minOccurs="0" maxOccurs="unbounded"/> + <xsd:choice> + <xsd:element name="delete" type="CT_Boolean" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="Group_DLbls" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_MarkerStyle"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="circle"/> + <xsd:enumeration value="dash"/> + <xsd:enumeration value="diamond"/> + <xsd:enumeration value="dot"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="picture"/> + <xsd:enumeration value="plus"/> + <xsd:enumeration value="square"/> + <xsd:enumeration value="star"/> + <xsd:enumeration value="triangle"/> + <xsd:enumeration value="x"/> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MarkerStyle"> + <xsd:attribute name="val" type="ST_MarkerStyle" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MarkerSize"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="2"/> + <xsd:maxInclusive value="72"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MarkerSize"> + <xsd:attribute name="val" type="ST_MarkerSize" default="5"/> + </xsd:complexType> + <xsd:complexType name="CT_Marker"> + <xsd:sequence> + <xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="size" type="CT_MarkerSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DPt"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TrendlineType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="exp"/> + <xsd:enumeration value="linear"/> + <xsd:enumeration value="log"/> + <xsd:enumeration value="movingAvg"/> + <xsd:enumeration value="poly"/> + <xsd:enumeration value="power"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TrendlineType"> + <xsd:attribute name="val" type="ST_TrendlineType" default="linear"/> + </xsd:complexType> + <xsd:simpleType name="ST_Order"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="2"/> + <xsd:maxInclusive value="6"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Order"> + <xsd:attribute name="val" type="ST_Order" default="2"/> + </xsd:complexType> + <xsd:simpleType name="ST_Period"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="2"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Period"> + <xsd:attribute name="val" type="ST_Period" default="2"/> + </xsd:complexType> + <xsd:complexType name="CT_TrendlineLbl"> + <xsd:sequence> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Trendline"> + <xsd:sequence> + <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendlineType" type="CT_TrendlineType" minOccurs="1" maxOccurs="1"/> + <xsd:element name="order" type="CT_Order" minOccurs="0" maxOccurs="1"/> + <xsd:element name="period" type="CT_Period" minOccurs="0" maxOccurs="1"/> + <xsd:element name="forward" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="backward" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="intercept" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dispRSqr" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dispEq" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendlineLbl" type="CT_TrendlineLbl" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_ErrDir"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="x"/> + <xsd:enumeration value="y"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ErrDir"> + <xsd:attribute name="val" type="ST_ErrDir" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_ErrBarType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="both"/> + <xsd:enumeration value="minus"/> + <xsd:enumeration value="plus"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ErrBarType"> + <xsd:attribute name="val" type="ST_ErrBarType" default="both"/> + </xsd:complexType> + <xsd:simpleType name="ST_ErrValType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="cust"/> + <xsd:enumeration value="fixedVal"/> + <xsd:enumeration value="percentage"/> + <xsd:enumeration value="stdDev"/> + <xsd:enumeration value="stdErr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ErrValType"> + <xsd:attribute name="val" type="ST_ErrValType" default="fixedVal"/> + </xsd:complexType> + <xsd:complexType name="CT_ErrBars"> + <xsd:sequence> + <xsd:element name="errDir" type="CT_ErrDir" minOccurs="0" maxOccurs="1"/> + <xsd:element name="errBarType" type="CT_ErrBarType" minOccurs="1" maxOccurs="1"/> + <xsd:element name="errValType" type="CT_ErrValType" minOccurs="1" maxOccurs="1"/> + <xsd:element name="noEndCap" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="plus" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minus" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_UpDownBar"> + <xsd:sequence> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_UpDownBars"> + <xsd:sequence> + <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="upBars" type="CT_UpDownBar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="downBars" type="CT_UpDownBar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_SerShared"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="order" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tx" type="CT_SerTx" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_LineSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ScatterSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/> + <xsd:element name="xVal" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="yVal" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_RadarSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BarSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_AreaSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PieSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BubbleSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trendline" type="CT_Trendline" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="errBars" type="CT_ErrBars" minOccurs="0" maxOccurs="2"/> + <xsd:element name="xVal" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="yVal" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bubbleSize" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SurfaceSer"> + <xsd:sequence> + <xsd:group ref="EG_SerShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cat" type="CT_AxDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="val" type="CT_NumDataSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Grouping"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="percentStacked"/> + <xsd:enumeration value="standard"/> + <xsd:enumeration value="stacked"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Grouping"> + <xsd:attribute name="val" type="ST_Grouping" default="standard"/> + </xsd:complexType> + <xsd:complexType name="CT_ChartLines"> + <xsd:sequence> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_LineChartShared"> + <xsd:sequence> + <xsd:element name="grouping" type="CT_Grouping" minOccurs="1" maxOccurs="1"/> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_LineSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dropLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_LineChart"> + <xsd:sequence> + <xsd:group ref="EG_LineChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hiLowLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + <xsd:element name="upDownBars" type="CT_UpDownBars" minOccurs="0" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smooth" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Line3DChart"> + <xsd:sequence> + <xsd:group ref="EG_LineChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gapDepth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="3" maxOccurs="3"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StockChart"> + <xsd:sequence> + <xsd:element name="ser" type="CT_LineSer" minOccurs="3" maxOccurs="4"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dropLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hiLowLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + <xsd:element name="upDownBars" type="CT_UpDownBars" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_ScatterStyle"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="line"/> + <xsd:enumeration value="lineMarker"/> + <xsd:enumeration value="marker"/> + <xsd:enumeration value="smooth"/> + <xsd:enumeration value="smoothMarker"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ScatterStyle"> + <xsd:attribute name="val" type="ST_ScatterStyle" default="marker"/> + </xsd:complexType> + <xsd:complexType name="CT_ScatterChart"> + <xsd:sequence> + <xsd:element name="scatterStyle" type="CT_ScatterStyle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_ScatterSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_RadarStyle"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="standard"/> + <xsd:enumeration value="marker"/> + <xsd:enumeration value="filled"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_RadarStyle"> + <xsd:attribute name="val" type="ST_RadarStyle" default="standard"/> + </xsd:complexType> + <xsd:complexType name="CT_RadarChart"> + <xsd:sequence> + <xsd:element name="radarStyle" type="CT_RadarStyle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_RadarSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_BarGrouping"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="percentStacked"/> + <xsd:enumeration value="clustered"/> + <xsd:enumeration value="standard"/> + <xsd:enumeration value="stacked"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_BarGrouping"> + <xsd:attribute name="val" type="ST_BarGrouping" default="clustered"/> + </xsd:complexType> + <xsd:simpleType name="ST_BarDir"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="bar"/> + <xsd:enumeration value="col"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_BarDir"> + <xsd:attribute name="val" type="ST_BarDir" default="col"/> + </xsd:complexType> + <xsd:simpleType name="ST_Shape"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="cone"/> + <xsd:enumeration value="coneToMax"/> + <xsd:enumeration value="box"/> + <xsd:enumeration value="cylinder"/> + <xsd:enumeration value="pyramid"/> + <xsd:enumeration value="pyramidToMax"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Shape"> + <xsd:attribute name="val" type="ST_Shape" default="box"/> + </xsd:complexType> + <xsd:group name="EG_BarChartShared"> + <xsd:sequence> + <xsd:element name="barDir" type="CT_BarDir" minOccurs="1" maxOccurs="1"/> + <xsd:element name="grouping" type="CT_BarGrouping" minOccurs="0" maxOccurs="1"/> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_BarSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_BarChart"> + <xsd:sequence> + <xsd:group ref="EG_BarChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="overlap" type="CT_Overlap" minOccurs="0" maxOccurs="1"/> + <xsd:element name="serLines" type="CT_ChartLines" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Bar3DChart"> + <xsd:sequence> + <xsd:group ref="EG_BarChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="gapDepth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_AreaChartShared"> + <xsd:sequence> + <xsd:element name="grouping" type="CT_Grouping" minOccurs="0" maxOccurs="1"/> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_AreaSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dropLines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_AreaChart"> + <xsd:sequence> + <xsd:group ref="EG_AreaChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Area3DChart"> + <xsd:sequence> + <xsd:group ref="EG_AreaChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gapDepth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_PieChartShared"> + <xsd:sequence> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_PieSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_PieChart"> + <xsd:sequence> + <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="firstSliceAng" type="CT_FirstSliceAng" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Pie3DChart"> + <xsd:sequence> + <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DoughnutChart"> + <xsd:sequence> + <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="firstSliceAng" type="CT_FirstSliceAng" minOccurs="0" maxOccurs="1"/> + <xsd:element name="holeSize" type="CT_HoleSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_OfPieType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="pie"/> + <xsd:enumeration value="bar"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_OfPieType"> + <xsd:attribute name="val" type="ST_OfPieType" default="pie"/> + </xsd:complexType> + <xsd:complexType name="CT_OfPieChart"> + <xsd:sequence> + <xsd:element name="ofPieType" type="CT_OfPieType" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_PieChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0" maxOccurs="1"/> + <xsd:element name="splitType" type="CT_SplitType" minOccurs="0" maxOccurs="1"/> + <xsd:element name="splitPos" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="custSplit" type="CT_CustSplit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="secondPieSize" type="CT_SecondPieSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="serLines" type="CT_ChartLines" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BubbleChart"> + <xsd:sequence> + <xsd:element name="varyColors" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_BubbleSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dLbls" type="CT_DLbls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bubbleScale" type="CT_BubbleScale" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showNegBubbles" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sizeRepresents" type="CT_SizeRepresents" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BandFmt"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BandFmts"> + <xsd:sequence> + <xsd:element name="bandFmt" type="CT_BandFmt" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_SurfaceChartShared"> + <xsd:sequence> + <xsd:element name="wireframe" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ser" type="CT_SurfaceSer" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="bandFmts" type="CT_BandFmts" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_SurfaceChart"> + <xsd:sequence> + <xsd:group ref="EG_SurfaceChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Surface3DChart"> + <xsd:sequence> + <xsd:group ref="EG_SurfaceChartShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="3" maxOccurs="3"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_AxPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="b"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="t"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_AxPos"> + <xsd:attribute name="val" type="ST_AxPos" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Crosses"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="autoZero"/> + <xsd:enumeration value="max"/> + <xsd:enumeration value="min"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Crosses"> + <xsd:attribute name="val" type="ST_Crosses" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_CrossBetween"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="between"/> + <xsd:enumeration value="midCat"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_CrossBetween"> + <xsd:attribute name="val" type="ST_CrossBetween" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TickMark"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="cross"/> + <xsd:enumeration value="in"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="out"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TickMark"> + <xsd:attribute name="val" type="ST_TickMark" default="cross"/> + </xsd:complexType> + <xsd:simpleType name="ST_TickLblPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="high"/> + <xsd:enumeration value="low"/> + <xsd:enumeration value="nextTo"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TickLblPos"> + <xsd:attribute name="val" type="ST_TickLblPos" default="nextTo"/> + </xsd:complexType> + <xsd:simpleType name="ST_Skip"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="1"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Skip"> + <xsd:attribute name="val" type="ST_Skip" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TimeUnit"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="days"/> + <xsd:enumeration value="months"/> + <xsd:enumeration value="years"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TimeUnit"> + <xsd:attribute name="val" type="ST_TimeUnit" default="days"/> + </xsd:complexType> + <xsd:simpleType name="ST_AxisUnit"> + <xsd:restriction base="xsd:double"> + <xsd:minExclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_AxisUnit"> + <xsd:attribute name="val" type="ST_AxisUnit" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_BuiltInUnit"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="hundreds"/> + <xsd:enumeration value="thousands"/> + <xsd:enumeration value="tenThousands"/> + <xsd:enumeration value="hundredThousands"/> + <xsd:enumeration value="millions"/> + <xsd:enumeration value="tenMillions"/> + <xsd:enumeration value="hundredMillions"/> + <xsd:enumeration value="billions"/> + <xsd:enumeration value="trillions"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_BuiltInUnit"> + <xsd:attribute name="val" type="ST_BuiltInUnit" default="thousands"/> + </xsd:complexType> + <xsd:simpleType name="ST_PictureFormat"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="stretch"/> + <xsd:enumeration value="stack"/> + <xsd:enumeration value="stackScale"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PictureFormat"> + <xsd:attribute name="val" type="ST_PictureFormat" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PictureStackUnit"> + <xsd:restriction base="xsd:double"> + <xsd:minExclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PictureStackUnit"> + <xsd:attribute name="val" type="ST_PictureStackUnit" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PictureOptions"> + <xsd:sequence> + <xsd:element name="applyToFront" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="applyToSides" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="applyToEnd" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pictureFormat" type="CT_PictureFormat" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pictureStackUnit" type="CT_PictureStackUnit" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DispUnitsLbl"> + <xsd:sequence> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tx" type="CT_Tx" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DispUnits"> + <xsd:sequence> + <xsd:choice> + <xsd:element name="custUnit" type="CT_Double" minOccurs="1" maxOccurs="1"/> + <xsd:element name="builtInUnit" type="CT_BuiltInUnit" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="dispUnitsLbl" type="CT_DispUnitsLbl" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Orientation"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="maxMin"/> + <xsd:enumeration value="minMax"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Orientation"> + <xsd:attribute name="val" type="ST_Orientation" default="minMax"/> + </xsd:complexType> + <xsd:simpleType name="ST_LogBase"> + <xsd:restriction base="xsd:double"> + <xsd:minInclusive value="2"/> + <xsd:maxInclusive value="1000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LogBase"> + <xsd:attribute name="val" type="ST_LogBase" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Scaling"> + <xsd:sequence> + <xsd:element name="logBase" type="CT_LogBase" minOccurs="0" maxOccurs="1"/> + <xsd:element name="orientation" type="CT_Orientation" minOccurs="0" maxOccurs="1"/> + <xsd:element name="max" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="min" type="CT_Double" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_LblOffset"> + <xsd:union memberTypes="ST_LblOffsetPercent ST_LblOffsetUShort"/> + </xsd:simpleType> + <xsd:simpleType name="ST_LblOffsetPercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-9][0-9][0-9])|1000)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LblOffsetUShort"> + <xsd:restriction base="xsd:unsignedShort"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="1000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LblOffset"> + <xsd:attribute name="val" type="ST_LblOffset" default="100%"/> + </xsd:complexType> + <xsd:group name="EG_AxShared"> + <xsd:sequence> + <xsd:element name="axId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="scaling" type="CT_Scaling" minOccurs="1" maxOccurs="1"/> + <xsd:element name="delete" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="axPos" type="CT_AxPos" minOccurs="1" maxOccurs="1"/> + <xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0" maxOccurs="1"/> + <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="crossAx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="crosses" type="CT_Crosses" minOccurs="1" maxOccurs="1"/> + <xsd:element name="crossesAt" type="CT_Double" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_CatAx"> + <xsd:sequence> + <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/> + <xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DateAx"> + <xsd:sequence> + <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="auto" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0" maxOccurs="1"/> + <xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SerAx"> + <xsd:sequence> + <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ValAx"> + <xsd:sequence> + <xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/> + <xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0" maxOccurs="1"/> + <xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PlotArea"> + <xsd:sequence> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="areaChart" type="CT_AreaChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="area3DChart" type="CT_Area3DChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lineChart" type="CT_LineChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="line3DChart" type="CT_Line3DChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="stockChart" type="CT_StockChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="radarChart" type="CT_RadarChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="scatterChart" type="CT_ScatterChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="pieChart" type="CT_PieChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="pie3DChart" type="CT_Pie3DChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="doughnutChart" type="CT_DoughnutChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="barChart" type="CT_BarChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="bar3DChart" type="CT_Bar3DChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="ofPieChart" type="CT_OfPieChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="surfaceChart" type="CT_SurfaceChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="surface3DChart" type="CT_Surface3DChart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="bubbleChart" type="CT_BubbleChart" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="valAx" type="CT_ValAx" minOccurs="1" maxOccurs="1"/> + <xsd:element name="catAx" type="CT_CatAx" minOccurs="1" maxOccurs="1"/> + <xsd:element name="dateAx" type="CT_DateAx" minOccurs="1" maxOccurs="1"/> + <xsd:element name="serAx" type="CT_SerAx" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="dTable" type="CT_DTable" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PivotFmt"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="marker" type="CT_Marker" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dLbl" type="CT_DLbl" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PivotFmts"> + <xsd:sequence> + <xsd:element name="pivotFmt" type="CT_PivotFmt" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_LegendPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="b"/> + <xsd:enumeration value="tr"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="t"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LegendPos"> + <xsd:attribute name="val" type="ST_LegendPos" default="r"/> + </xsd:complexType> + <xsd:group name="EG_LegendEntryData"> + <xsd:sequence> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_LegendEntry"> + <xsd:sequence> + <xsd:element name="idx" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:choice> + <xsd:element name="delete" type="CT_Boolean" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_LegendEntryData" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Legend"> + <xsd:sequence> + <xsd:element name="legendPos" type="CT_LegendPos" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legendEntry" type="CT_LegendEntry" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/> + <xsd:element name="overlay" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_DispBlanksAs"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="span"/> + <xsd:enumeration value="gap"/> + <xsd:enumeration value="zero"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DispBlanksAs"> + <xsd:attribute name="val" type="ST_DispBlanksAs" default="zero"/> + </xsd:complexType> + <xsd:complexType name="CT_Chart"> + <xsd:sequence> + <xsd:element name="title" type="CT_Title" minOccurs="0" maxOccurs="1"/> + <xsd:element name="autoTitleDeleted" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pivotFmts" type="CT_PivotFmts" minOccurs="0" maxOccurs="1"/> + <xsd:element name="view3D" type="CT_View3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="floor" type="CT_Surface" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sideWall" type="CT_Surface" minOccurs="0" maxOccurs="1"/> + <xsd:element name="backWall" type="CT_Surface" minOccurs="0" maxOccurs="1"/> + <xsd:element name="plotArea" type="CT_PlotArea" minOccurs="1" maxOccurs="1"/> + <xsd:element name="legend" type="CT_Legend" minOccurs="0" maxOccurs="1"/> + <xsd:element name="plotVisOnly" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dispBlanksAs" type="CT_DispBlanksAs" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showDLblsOverMax" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Style"> + <xsd:restriction base="xsd:unsignedByte"> + <xsd:minInclusive value="1"/> + <xsd:maxInclusive value="48"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Style"> + <xsd:attribute name="val" type="ST_Style" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotSource"> + <xsd:sequence> + <xsd:element name="name" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fmtId" type="CT_UnsignedInt" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Protection"> + <xsd:sequence> + <xsd:element name="chartObject" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="data" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="formatting" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="selection" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="userInterface" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_HeaderFooter"> + <xsd:sequence> + <xsd:element name="oddHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oddFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="evenHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="evenFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="alignWithMargins" type="xsd:boolean" default="true"/> + <xsd:attribute name="differentOddEven" type="xsd:boolean" default="false"/> + <xsd:attribute name="differentFirst" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_PageMargins"> + <xsd:attribute name="l" type="xsd:double" use="required"/> + <xsd:attribute name="r" type="xsd:double" use="required"/> + <xsd:attribute name="t" type="xsd:double" use="required"/> + <xsd:attribute name="b" type="xsd:double" use="required"/> + <xsd:attribute name="header" type="xsd:double" use="required"/> + <xsd:attribute name="footer" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PageSetupOrientation"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="default"/> + <xsd:enumeration value="portrait"/> + <xsd:enumeration value="landscape"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ExternalData"> + <xsd:sequence> + <xsd:element name="autoUpdate" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PageSetup"> + <xsd:attribute name="paperSize" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="paperHeight" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="paperWidth" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="firstPageNumber" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="orientation" type="ST_PageSetupOrientation" use="optional" + default="default"/> + <xsd:attribute name="blackAndWhite" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="draft" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="useFirstPageNumber" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="horizontalDpi" type="xsd:int" use="optional" default="600"/> + <xsd:attribute name="verticalDpi" type="xsd:int" use="optional" default="600"/> + <xsd:attribute name="copies" type="xsd:unsignedInt" use="optional" default="1"/> + </xsd:complexType> + <xsd:complexType name="CT_PrintSettings"> + <xsd:sequence> + <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawingHF" type="CT_RelId" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ChartSpace"> + <xsd:sequence> + <xsd:element name="date1904" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lang" type="CT_TextLanguageID" minOccurs="0" maxOccurs="1"/> + <xsd:element name="roundedCorners" type="CT_Boolean" minOccurs="0" maxOccurs="1"/> + <xsd:element name="style" type="CT_Style" minOccurs="0" maxOccurs="1"/> + <xsd:element name="clrMapOvr" type="a:CT_ColorMapping" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pivotSource" type="CT_PivotSource" minOccurs="0" maxOccurs="1"/> + <xsd:element name="protection" type="CT_Protection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="chart" type="CT_Chart" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="externalData" type="CT_ExternalData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="printSettings" type="CT_PrintSettings" minOccurs="0" maxOccurs="1"/> + <xsd:element name="userShapes" type="CT_RelId" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="chartSpace" type="CT_ChartSpace"/> + <xsd:element name="userShapes" type="cdr:CT_Drawing"/> + <xsd:element name="chart" type="CT_RelId"/> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd new file mode 100644 index 0000000..afa4f46 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd new file mode 100644 index 0000000..64e66b8 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd @@ -0,0 +1,1085 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://schemas.openxmlformats.org/drawingml/2006/diagram" + xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/diagram" + elementFormDefault="qualified" attributeFormDefault="unqualified"> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + schemaLocation="shared-relationshipReference.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main" + schemaLocation="dml-main.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + schemaLocation="shared-commonSimpleTypes.xsd"/> + <xsd:complexType name="CT_CTName"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CTDescription"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CTCategory"> + <xsd:attribute name="type" type="xsd:anyURI" use="required"/> + <xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CTCategories"> + <xsd:sequence minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="cat" type="CT_CTCategory" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_ClrAppMethod"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="span"/> + <xsd:enumeration value="cycle"/> + <xsd:enumeration value="repeat"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HueDir"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="cw"/> + <xsd:enumeration value="ccw"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Colors"> + <xsd:sequence> + <xsd:group ref="a:EG_ColorChoice" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="meth" type="ST_ClrAppMethod" use="optional" default="span"/> + <xsd:attribute name="hueDir" type="ST_HueDir" use="optional" default="cw"/> + </xsd:complexType> + <xsd:complexType name="CT_CTStyleLabel"> + <xsd:sequence> + <xsd:element name="fillClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="linClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="effectClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txLinClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txFillClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txEffectClrLst" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ColorTransform"> + <xsd:sequence> + <xsd:element name="title" type="CT_CTName" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_CTDescription" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_CTCategories" minOccurs="0"/> + <xsd:element name="styleLbl" type="CT_CTStyleLabel" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:element name="colorsDef" type="CT_ColorTransform"/> + <xsd:complexType name="CT_ColorTransformHeader"> + <xsd:sequence> + <xsd:element name="title" type="CT_CTName" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_CTDescription" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_CTCategories" minOccurs="0"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="required"/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + <xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/> + </xsd:complexType> + <xsd:element name="colorsDefHdr" type="CT_ColorTransformHeader"/> + <xsd:complexType name="CT_ColorTransformHeaderLst"> + <xsd:sequence> + <xsd:element name="colorsDefHdr" type="CT_ColorTransformHeader" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="colorsDefHdrLst" type="CT_ColorTransformHeaderLst"/> + <xsd:simpleType name="ST_PtType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="node"/> + <xsd:enumeration value="asst"/> + <xsd:enumeration value="doc"/> + <xsd:enumeration value="pres"/> + <xsd:enumeration value="parTrans"/> + <xsd:enumeration value="sibTrans"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Pt"> + <xsd:sequence> + <xsd:element name="prSet" type="CT_ElemPropSet" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="t" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="modelId" type="ST_ModelId" use="required"/> + <xsd:attribute name="type" type="ST_PtType" use="optional" default="node"/> + <xsd:attribute name="cxnId" type="ST_ModelId" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_PtList"> + <xsd:sequence> + <xsd:element name="pt" type="CT_Pt" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_CxnType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="parOf"/> + <xsd:enumeration value="presOf"/> + <xsd:enumeration value="presParOf"/> + <xsd:enumeration value="unknownRelationship"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Cxn"> + <xsd:sequence> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="modelId" type="ST_ModelId" use="required"/> + <xsd:attribute name="type" type="ST_CxnType" use="optional" default="parOf"/> + <xsd:attribute name="srcId" type="ST_ModelId" use="required"/> + <xsd:attribute name="destId" type="ST_ModelId" use="required"/> + <xsd:attribute name="srcOrd" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="destOrd" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="parTransId" type="ST_ModelId" use="optional" default="0"/> + <xsd:attribute name="sibTransId" type="ST_ModelId" use="optional" default="0"/> + <xsd:attribute name="presId" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_CxnList"> + <xsd:sequence> + <xsd:element name="cxn" type="CT_Cxn" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DataModel"> + <xsd:sequence> + <xsd:element name="ptLst" type="CT_PtList"/> + <xsd:element name="cxnLst" type="CT_CxnList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bg" type="a:CT_BackgroundFormatting" minOccurs="0"/> + <xsd:element name="whole" type="a:CT_WholeE2oFormatting" minOccurs="0"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="dataModel" type="CT_DataModel"/> + <xsd:attributeGroup name="AG_IteratorAttributes"> + <xsd:attribute name="axis" type="ST_AxisTypes" use="optional" default="none"/> + <xsd:attribute name="ptType" type="ST_ElementTypes" use="optional" default="all"/> + <xsd:attribute name="hideLastTrans" type="ST_Booleans" use="optional" default="true"/> + <xsd:attribute name="st" type="ST_Ints" use="optional" default="1"/> + <xsd:attribute name="cnt" type="ST_UnsignedInts" use="optional" default="0"/> + <xsd:attribute name="step" type="ST_Ints" use="optional" default="1"/> + </xsd:attributeGroup> + <xsd:attributeGroup name="AG_ConstraintAttributes"> + <xsd:attribute name="type" type="ST_ConstraintType" use="required"/> + <xsd:attribute name="for" type="ST_ConstraintRelationship" use="optional" default="self"/> + <xsd:attribute name="forName" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="ptType" type="ST_ElementType" use="optional" default="all"/> + </xsd:attributeGroup> + <xsd:attributeGroup name="AG_ConstraintRefAttributes"> + <xsd:attribute name="refType" type="ST_ConstraintType" use="optional" default="none"/> + <xsd:attribute name="refFor" type="ST_ConstraintRelationship" use="optional" default="self"/> + <xsd:attribute name="refForName" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="refPtType" type="ST_ElementType" use="optional" default="all"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_Constraint"> + <xsd:sequence> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_ConstraintAttributes"/> + <xsd:attributeGroup ref="AG_ConstraintRefAttributes"/> + <xsd:attribute name="op" type="ST_BoolOperator" use="optional" default="none"/> + <xsd:attribute name="val" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="fact" type="xsd:double" use="optional" default="1"/> + </xsd:complexType> + <xsd:complexType name="CT_Constraints"> + <xsd:sequence> + <xsd:element name="constr" type="CT_Constraint" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NumericRule"> + <xsd:sequence> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_ConstraintAttributes"/> + <xsd:attribute name="val" type="xsd:double" use="optional" default="NaN"/> + <xsd:attribute name="fact" type="xsd:double" use="optional" default="NaN"/> + <xsd:attribute name="max" type="xsd:double" use="optional" default="NaN"/> + </xsd:complexType> + <xsd:complexType name="CT_Rules"> + <xsd:sequence> + <xsd:element name="rule" type="CT_NumericRule" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PresentationOf"> + <xsd:sequence> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_IteratorAttributes"/> + </xsd:complexType> + <xsd:simpleType name="ST_LayoutShapeType" final="restriction"> + <xsd:union memberTypes="a:ST_ShapeType ST_OutputShapeType"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Index1"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="1"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Adj"> + <xsd:attribute name="idx" type="ST_Index1" use="required"/> + <xsd:attribute name="val" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AdjLst"> + <xsd:sequence> + <xsd:element name="adj" type="CT_Adj" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Shape"> + <xsd:sequence> + <xsd:element name="adjLst" type="CT_AdjLst" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rot" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="type" type="ST_LayoutShapeType" use="optional" default="none"/> + <xsd:attribute ref="r:blip" use="optional"/> + <xsd:attribute name="zOrderOff" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="hideGeom" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="lkTxEntry" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="blipPhldr" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Parameter"> + <xsd:attribute name="type" type="ST_ParameterId" use="required"/> + <xsd:attribute name="val" type="ST_ParameterVal" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Algorithm"> + <xsd:sequence> + <xsd:element name="param" type="CT_Parameter" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_AlgorithmType" use="required"/> + <xsd:attribute name="rev" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_LayoutNode"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/> + <xsd:element name="varLst" type="CT_LayoutVariablePropertySet" minOccurs="0" maxOccurs="1"/> + <xsd:element name="forEach" type="CT_ForEach"/> + <xsd:element name="layoutNode" type="CT_LayoutNode"/> + <xsd:element name="choose" type="CT_Choose"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="styleLbl" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="chOrder" type="ST_ChildOrderType" use="optional" default="b"/> + <xsd:attribute name="moveWith" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_ForEach"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/> + <xsd:element name="forEach" type="CT_ForEach"/> + <xsd:element name="layoutNode" type="CT_LayoutNode"/> + <xsd:element name="choose" type="CT_Choose"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="ref" type="xsd:string" use="optional" default=""/> + <xsd:attributeGroup ref="AG_IteratorAttributes"/> + </xsd:complexType> + <xsd:complexType name="CT_When"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/> + <xsd:element name="forEach" type="CT_ForEach"/> + <xsd:element name="layoutNode" type="CT_LayoutNode"/> + <xsd:element name="choose" type="CT_Choose"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + <xsd:attributeGroup ref="AG_IteratorAttributes"/> + <xsd:attribute name="func" type="ST_FunctionType" use="required"/> + <xsd:attribute name="arg" type="ST_FunctionArgument" use="optional" default="none"/> + <xsd:attribute name="op" type="ST_FunctionOperator" use="required"/> + <xsd:attribute name="val" type="ST_FunctionValue" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Otherwise"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="alg" type="CT_Algorithm" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shape" type="CT_Shape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="presOf" type="CT_PresentationOf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="constrLst" type="CT_Constraints" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ruleLst" type="CT_Rules" minOccurs="0" maxOccurs="1"/> + <xsd:element name="forEach" type="CT_ForEach"/> + <xsd:element name="layoutNode" type="CT_LayoutNode"/> + <xsd:element name="choose" type="CT_Choose"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_Choose"> + <xsd:sequence> + <xsd:element name="if" type="CT_When" maxOccurs="unbounded"/> + <xsd:element name="else" type="CT_Otherwise" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_SampleData"> + <xsd:sequence> + <xsd:element name="dataModel" type="CT_DataModel" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="useDef" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Category"> + <xsd:attribute name="type" type="xsd:anyURI" use="required"/> + <xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Categories"> + <xsd:sequence> + <xsd:element name="cat" type="CT_Category" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Name"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Description"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DiagramDefinition"> + <xsd:sequence> + <xsd:element name="title" type="CT_Name" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_Description" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_Categories" minOccurs="0"/> + <xsd:element name="sampData" type="CT_SampleData" minOccurs="0"/> + <xsd:element name="styleData" type="CT_SampleData" minOccurs="0"/> + <xsd:element name="clrData" type="CT_SampleData" minOccurs="0"/> + <xsd:element name="layoutNode" type="CT_LayoutNode"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + <xsd:attribute name="defStyle" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:element name="layoutDef" type="CT_DiagramDefinition"/> + <xsd:complexType name="CT_DiagramDefinitionHeader"> + <xsd:sequence> + <xsd:element name="title" type="CT_Name" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_Description" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_Categories" minOccurs="0"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="required"/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + <xsd:attribute name="defStyle" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/> + </xsd:complexType> + <xsd:element name="layoutDefHdr" type="CT_DiagramDefinitionHeader"/> + <xsd:complexType name="CT_DiagramDefinitionHeaderLst"> + <xsd:sequence> + <xsd:element name="layoutDefHdr" type="CT_DiagramDefinitionHeader" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="layoutDefHdrLst" type="CT_DiagramDefinitionHeaderLst"/> + <xsd:complexType name="CT_RelIds"> + <xsd:attribute ref="r:dm" use="required"/> + <xsd:attribute ref="r:lo" use="required"/> + <xsd:attribute ref="r:qs" use="required"/> + <xsd:attribute ref="r:cs" use="required"/> + </xsd:complexType> + <xsd:element name="relIds" type="CT_RelIds"/> + <xsd:simpleType name="ST_ParameterVal"> + <xsd:union + memberTypes="ST_DiagramHorizontalAlignment ST_VerticalAlignment ST_ChildDirection ST_ChildAlignment ST_SecondaryChildAlignment ST_LinearDirection ST_SecondaryLinearDirection ST_StartingElement ST_BendPoint ST_ConnectorRouting ST_ArrowheadStyle ST_ConnectorDimension ST_RotationPath ST_CenterShapeMapping ST_NodeHorizontalAlignment ST_NodeVerticalAlignment ST_FallbackDimension ST_TextDirection ST_PyramidAccentPosition ST_PyramidAccentTextMargin ST_TextBlockDirection ST_TextAnchorHorizontal ST_TextAnchorVertical ST_DiagramTextAlignment ST_AutoTextRotation ST_GrowDirection ST_FlowDirection ST_ContinueDirection ST_Breakpoint ST_Offset ST_HierarchyAlignment xsd:int xsd:double xsd:boolean xsd:string ST_ConnectorPoint" + /> + </xsd:simpleType> + <xsd:simpleType name="ST_ModelId"> + <xsd:union memberTypes="xsd:int s:ST_Guid"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PrSetCustVal"> + <xsd:union memberTypes="s:ST_Percentage xsd:int"/> + </xsd:simpleType> + <xsd:complexType name="CT_ElemPropSet"> + <xsd:sequence> + <xsd:element name="presLayoutVars" type="CT_LayoutVariablePropertySet" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="presAssocID" type="ST_ModelId" use="optional"/> + <xsd:attribute name="presName" type="xsd:string" use="optional"/> + <xsd:attribute name="presStyleLbl" type="xsd:string" use="optional"/> + <xsd:attribute name="presStyleIdx" type="xsd:int" use="optional"/> + <xsd:attribute name="presStyleCnt" type="xsd:int" use="optional"/> + <xsd:attribute name="loTypeId" type="xsd:string" use="optional"/> + <xsd:attribute name="loCatId" type="xsd:string" use="optional"/> + <xsd:attribute name="qsTypeId" type="xsd:string" use="optional"/> + <xsd:attribute name="qsCatId" type="xsd:string" use="optional"/> + <xsd:attribute name="csTypeId" type="xsd:string" use="optional"/> + <xsd:attribute name="csCatId" type="xsd:string" use="optional"/> + <xsd:attribute name="coherent3DOff" type="xsd:boolean" use="optional"/> + <xsd:attribute name="phldrT" type="xsd:string" use="optional"/> + <xsd:attribute name="phldr" type="xsd:boolean" use="optional"/> + <xsd:attribute name="custAng" type="xsd:int" use="optional"/> + <xsd:attribute name="custFlipVert" type="xsd:boolean" use="optional"/> + <xsd:attribute name="custFlipHor" type="xsd:boolean" use="optional"/> + <xsd:attribute name="custSzX" type="xsd:int" use="optional"/> + <xsd:attribute name="custSzY" type="xsd:int" use="optional"/> + <xsd:attribute name="custScaleX" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custScaleY" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custT" type="xsd:boolean" use="optional"/> + <xsd:attribute name="custLinFactX" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custLinFactY" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custLinFactNeighborX" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custLinFactNeighborY" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custRadScaleRad" type="ST_PrSetCustVal" use="optional"/> + <xsd:attribute name="custRadScaleInc" type="ST_PrSetCustVal" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Direction" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="norm"/> + <xsd:enumeration value="rev"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HierBranchStyle" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="hang"/> + <xsd:enumeration value="std"/> + <xsd:enumeration value="init"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnimOneStr" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="one"/> + <xsd:enumeration value="branch"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnimLvlStr" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="lvl"/> + <xsd:enumeration value="ctr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_OrgChart"> + <xsd:attribute name="val" type="xsd:boolean" default="false" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_NodeCount"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="-1"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ChildMax"> + <xsd:attribute name="val" type="ST_NodeCount" default="-1" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ChildPref"> + <xsd:attribute name="val" type="ST_NodeCount" default="-1" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_BulletEnabled"> + <xsd:attribute name="val" type="xsd:boolean" default="false" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Direction"> + <xsd:attribute name="val" type="ST_Direction" default="norm" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_HierBranchStyle"> + <xsd:attribute name="val" type="ST_HierBranchStyle" default="std" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_AnimOne"> + <xsd:attribute name="val" type="ST_AnimOneStr" default="one" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_AnimLvl"> + <xsd:attribute name="val" type="ST_AnimLvlStr" default="none" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_ResizeHandlesStr" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="exact"/> + <xsd:enumeration value="rel"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ResizeHandles"> + <xsd:attribute name="val" type="ST_ResizeHandlesStr" default="rel" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_LayoutVariablePropertySet"> + <xsd:sequence> + <xsd:element name="orgChart" type="CT_OrgChart" minOccurs="0" maxOccurs="1"/> + <xsd:element name="chMax" type="CT_ChildMax" minOccurs="0" maxOccurs="1"/> + <xsd:element name="chPref" type="CT_ChildPref" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bulletEnabled" type="CT_BulletEnabled" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dir" type="CT_Direction" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hierBranch" type="CT_HierBranchStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="animOne" type="CT_AnimOne" minOccurs="0" maxOccurs="1"/> + <xsd:element name="animLvl" type="CT_AnimLvl" minOccurs="0" maxOccurs="1"/> + <xsd:element name="resizeHandles" type="CT_ResizeHandles" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SDName"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SDDescription"> + <xsd:attribute name="lang" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SDCategory"> + <xsd:attribute name="type" type="xsd:anyURI" use="required"/> + <xsd:attribute name="pri" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SDCategories"> + <xsd:sequence minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="cat" type="CT_SDCategory" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TextProps"> + <xsd:sequence> + <xsd:group ref="a:EG_Text3D" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StyleLabel"> + <xsd:sequence> + <xsd:element name="scene3d" type="a:CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sp3d" type="a:CT_Shape3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txPr" type="CT_TextProps" minOccurs="0" 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:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_StyleDefinition"> + <xsd:sequence> + <xsd:element name="title" type="CT_SDName" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_SDDescription" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_SDCategories" minOccurs="0"/> + <xsd:element name="scene3d" type="a:CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="styleLbl" type="CT_StyleLabel" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:element name="styleDef" type="CT_StyleDefinition"/> + <xsd:complexType name="CT_StyleDefinitionHeader"> + <xsd:sequence> + <xsd:element name="title" type="CT_SDName" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="desc" type="CT_SDDescription" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="catLst" type="CT_SDCategories" minOccurs="0"/> + <xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="uniqueId" type="xsd:string" use="required"/> + <xsd:attribute name="minVer" type="xsd:string" use="optional"/> + <xsd:attribute name="resId" type="xsd:int" use="optional" default="0"/> + </xsd:complexType> + <xsd:element name="styleDefHdr" type="CT_StyleDefinitionHeader"/> + <xsd:complexType name="CT_StyleDefinitionHeaderLst"> + <xsd:sequence> + <xsd:element name="styleDefHdr" type="CT_StyleDefinitionHeader" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="styleDefHdrLst" type="CT_StyleDefinitionHeaderLst"/> + <xsd:simpleType name="ST_AlgorithmType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="composite"/> + <xsd:enumeration value="conn"/> + <xsd:enumeration value="cycle"/> + <xsd:enumeration value="hierChild"/> + <xsd:enumeration value="hierRoot"/> + <xsd:enumeration value="pyra"/> + <xsd:enumeration value="lin"/> + <xsd:enumeration value="sp"/> + <xsd:enumeration value="tx"/> + <xsd:enumeration value="snake"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AxisType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="self"/> + <xsd:enumeration value="ch"/> + <xsd:enumeration value="des"/> + <xsd:enumeration value="desOrSelf"/> + <xsd:enumeration value="par"/> + <xsd:enumeration value="ancst"/> + <xsd:enumeration value="ancstOrSelf"/> + <xsd:enumeration value="followSib"/> + <xsd:enumeration value="precedSib"/> + <xsd:enumeration value="follow"/> + <xsd:enumeration value="preced"/> + <xsd:enumeration value="root"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AxisTypes"> + <xsd:list itemType="ST_AxisType"/> + </xsd:simpleType> + <xsd:simpleType name="ST_BoolOperator" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="equ"/> + <xsd:enumeration value="gte"/> + <xsd:enumeration value="lte"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ChildOrderType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="b"/> + <xsd:enumeration value="t"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConstraintType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="alignOff"/> + <xsd:enumeration value="begMarg"/> + <xsd:enumeration value="bendDist"/> + <xsd:enumeration value="begPad"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="bMarg"/> + <xsd:enumeration value="bOff"/> + <xsd:enumeration value="ctrX"/> + <xsd:enumeration value="ctrXOff"/> + <xsd:enumeration value="ctrY"/> + <xsd:enumeration value="ctrYOff"/> + <xsd:enumeration value="connDist"/> + <xsd:enumeration value="diam"/> + <xsd:enumeration value="endMarg"/> + <xsd:enumeration value="endPad"/> + <xsd:enumeration value="h"/> + <xsd:enumeration value="hArH"/> + <xsd:enumeration value="hOff"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="lMarg"/> + <xsd:enumeration value="lOff"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="rMarg"/> + <xsd:enumeration value="rOff"/> + <xsd:enumeration value="primFontSz"/> + <xsd:enumeration value="pyraAcctRatio"/> + <xsd:enumeration value="secFontSz"/> + <xsd:enumeration value="sibSp"/> + <xsd:enumeration value="secSibSp"/> + <xsd:enumeration value="sp"/> + <xsd:enumeration value="stemThick"/> + <xsd:enumeration value="t"/> + <xsd:enumeration value="tMarg"/> + <xsd:enumeration value="tOff"/> + <xsd:enumeration value="userA"/> + <xsd:enumeration value="userB"/> + <xsd:enumeration value="userC"/> + <xsd:enumeration value="userD"/> + <xsd:enumeration value="userE"/> + <xsd:enumeration value="userF"/> + <xsd:enumeration value="userG"/> + <xsd:enumeration value="userH"/> + <xsd:enumeration value="userI"/> + <xsd:enumeration value="userJ"/> + <xsd:enumeration value="userK"/> + <xsd:enumeration value="userL"/> + <xsd:enumeration value="userM"/> + <xsd:enumeration value="userN"/> + <xsd:enumeration value="userO"/> + <xsd:enumeration value="userP"/> + <xsd:enumeration value="userQ"/> + <xsd:enumeration value="userR"/> + <xsd:enumeration value="userS"/> + <xsd:enumeration value="userT"/> + <xsd:enumeration value="userU"/> + <xsd:enumeration value="userV"/> + <xsd:enumeration value="userW"/> + <xsd:enumeration value="userX"/> + <xsd:enumeration value="userY"/> + <xsd:enumeration value="userZ"/> + <xsd:enumeration value="w"/> + <xsd:enumeration value="wArH"/> + <xsd:enumeration value="wOff"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConstraintRelationship" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="self"/> + <xsd:enumeration value="ch"/> + <xsd:enumeration value="des"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ElementType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="all"/> + <xsd:enumeration value="doc"/> + <xsd:enumeration value="node"/> + <xsd:enumeration value="norm"/> + <xsd:enumeration value="nonNorm"/> + <xsd:enumeration value="asst"/> + <xsd:enumeration value="nonAsst"/> + <xsd:enumeration value="parTrans"/> + <xsd:enumeration value="pres"/> + <xsd:enumeration value="sibTrans"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ElementTypes"> + <xsd:list itemType="ST_ElementType"/> + </xsd:simpleType> + <xsd:simpleType name="ST_ParameterId" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="horzAlign"/> + <xsd:enumeration value="vertAlign"/> + <xsd:enumeration value="chDir"/> + <xsd:enumeration value="chAlign"/> + <xsd:enumeration value="secChAlign"/> + <xsd:enumeration value="linDir"/> + <xsd:enumeration value="secLinDir"/> + <xsd:enumeration value="stElem"/> + <xsd:enumeration value="bendPt"/> + <xsd:enumeration value="connRout"/> + <xsd:enumeration value="begSty"/> + <xsd:enumeration value="endSty"/> + <xsd:enumeration value="dim"/> + <xsd:enumeration value="rotPath"/> + <xsd:enumeration value="ctrShpMap"/> + <xsd:enumeration value="nodeHorzAlign"/> + <xsd:enumeration value="nodeVertAlign"/> + <xsd:enumeration value="fallback"/> + <xsd:enumeration value="txDir"/> + <xsd:enumeration value="pyraAcctPos"/> + <xsd:enumeration value="pyraAcctTxMar"/> + <xsd:enumeration value="txBlDir"/> + <xsd:enumeration value="txAnchorHorz"/> + <xsd:enumeration value="txAnchorVert"/> + <xsd:enumeration value="txAnchorHorzCh"/> + <xsd:enumeration value="txAnchorVertCh"/> + <xsd:enumeration value="parTxLTRAlign"/> + <xsd:enumeration value="parTxRTLAlign"/> + <xsd:enumeration value="shpTxLTRAlignCh"/> + <xsd:enumeration value="shpTxRTLAlignCh"/> + <xsd:enumeration value="autoTxRot"/> + <xsd:enumeration value="grDir"/> + <xsd:enumeration value="flowDir"/> + <xsd:enumeration value="contDir"/> + <xsd:enumeration value="bkpt"/> + <xsd:enumeration value="off"/> + <xsd:enumeration value="hierAlign"/> + <xsd:enumeration value="bkPtFixedVal"/> + <xsd:enumeration value="stBulletLvl"/> + <xsd:enumeration value="stAng"/> + <xsd:enumeration value="spanAng"/> + <xsd:enumeration value="ar"/> + <xsd:enumeration value="lnSpPar"/> + <xsd:enumeration value="lnSpAfParP"/> + <xsd:enumeration value="lnSpCh"/> + <xsd:enumeration value="lnSpAfChP"/> + <xsd:enumeration value="rtShortDist"/> + <xsd:enumeration value="alignTx"/> + <xsd:enumeration value="pyraLvlNode"/> + <xsd:enumeration value="pyraAcctBkgdNode"/> + <xsd:enumeration value="pyraAcctTxNode"/> + <xsd:enumeration value="srcNode"/> + <xsd:enumeration value="dstNode"/> + <xsd:enumeration value="begPts"/> + <xsd:enumeration value="endPts"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Ints"> + <xsd:list itemType="xsd:int"/> + </xsd:simpleType> + <xsd:simpleType name="ST_UnsignedInts"> + <xsd:list itemType="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Booleans"> + <xsd:list itemType="xsd:boolean"/> + </xsd:simpleType> + <xsd:simpleType name="ST_FunctionType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="cnt"/> + <xsd:enumeration value="pos"/> + <xsd:enumeration value="revPos"/> + <xsd:enumeration value="posEven"/> + <xsd:enumeration value="posOdd"/> + <xsd:enumeration value="var"/> + <xsd:enumeration value="depth"/> + <xsd:enumeration value="maxDepth"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FunctionOperator" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="equ"/> + <xsd:enumeration value="neq"/> + <xsd:enumeration value="gt"/> + <xsd:enumeration value="lt"/> + <xsd:enumeration value="gte"/> + <xsd:enumeration value="lte"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DiagramHorizontalAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_VerticalAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="t"/> + <xsd:enumeration value="mid"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ChildDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="horz"/> + <xsd:enumeration value="vert"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ChildAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="t"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_SecondaryChildAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="t"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="l"/> + <xsd:enumeration value="r"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LinearDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="fromL"/> + <xsd:enumeration value="fromR"/> + <xsd:enumeration value="fromT"/> + <xsd:enumeration value="fromB"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_SecondaryLinearDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="fromL"/> + <xsd:enumeration value="fromR"/> + <xsd:enumeration value="fromT"/> + <xsd:enumeration value="fromB"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_StartingElement" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="node"/> + <xsd:enumeration value="trans"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_RotationPath" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="alongPath"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CenterShapeMapping" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="fNode"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_BendPoint" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="beg"/> + <xsd:enumeration value="def"/> + <xsd:enumeration value="end"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConnectorRouting" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="stra"/> + <xsd:enumeration value="bend"/> + <xsd:enumeration value="curve"/> + <xsd:enumeration value="longCurve"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ArrowheadStyle" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="arr"/> + <xsd:enumeration value="noArr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConnectorDimension" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="1D"/> + <xsd:enumeration value="2D"/> + <xsd:enumeration value="cust"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConnectorPoint" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="bCtr"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="midL"/> + <xsd:enumeration value="midR"/> + <xsd:enumeration value="tCtr"/> + <xsd:enumeration value="bL"/> + <xsd:enumeration value="bR"/> + <xsd:enumeration value="tL"/> + <xsd:enumeration value="tR"/> + <xsd:enumeration value="radial"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_NodeHorizontalAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="r"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_NodeVerticalAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="t"/> + <xsd:enumeration value="mid"/> + <xsd:enumeration value="b"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FallbackDimension" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="1D"/> + <xsd:enumeration value="2D"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="fromT"/> + <xsd:enumeration value="fromB"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PyramidAccentPosition" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="bef"/> + <xsd:enumeration value="aft"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PyramidAccentTextMargin" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="step"/> + <xsd:enumeration value="stack"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextBlockDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="horz"/> + <xsd:enumeration value="vert"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextAnchorHorizontal" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="ctr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextAnchorVertical" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="t"/> + <xsd:enumeration value="mid"/> + <xsd:enumeration value="b"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DiagramTextAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="r"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AutoTextRotation" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="upr"/> + <xsd:enumeration value="grav"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_GrowDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="tL"/> + <xsd:enumeration value="tR"/> + <xsd:enumeration value="bL"/> + <xsd:enumeration value="bR"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FlowDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="row"/> + <xsd:enumeration value="col"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ContinueDirection" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="revDir"/> + <xsd:enumeration value="sameDir"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Breakpoint" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="endCnv"/> + <xsd:enumeration value="bal"/> + <xsd:enumeration value="fixed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Offset" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="off"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HierarchyAlignment" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="tL"/> + <xsd:enumeration value="tR"/> + <xsd:enumeration value="tCtrCh"/> + <xsd:enumeration value="tCtrDes"/> + <xsd:enumeration value="bL"/> + <xsd:enumeration value="bR"/> + <xsd:enumeration value="bCtrCh"/> + <xsd:enumeration value="bCtrDes"/> + <xsd:enumeration value="lT"/> + <xsd:enumeration value="lB"/> + <xsd:enumeration value="lCtrCh"/> + <xsd:enumeration value="lCtrDes"/> + <xsd:enumeration value="rT"/> + <xsd:enumeration value="rB"/> + <xsd:enumeration value="rCtrCh"/> + <xsd:enumeration value="rCtrDes"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FunctionValue" final="restriction"> + <xsd:union + memberTypes="xsd:int xsd:boolean ST_Direction ST_HierBranchStyle ST_AnimOneStr ST_AnimLvlStr ST_ResizeHandlesStr" + /> + </xsd:simpleType> + <xsd:simpleType name="ST_VariableType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="orgChart"/> + <xsd:enumeration value="chMax"/> + <xsd:enumeration value="chPref"/> + <xsd:enumeration value="bulEnabled"/> + <xsd:enumeration value="dir"/> + <xsd:enumeration value="hierBranch"/> + <xsd:enumeration value="animOne"/> + <xsd:enumeration value="animLvl"/> + <xsd:enumeration value="resizeHandles"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FunctionArgument" final="restriction"> + <xsd:union memberTypes="ST_VariableType"/> + </xsd:simpleType> + <xsd:simpleType name="ST_OutputShapeType" final="restriction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="conn"/> + </xsd:restriction> + </xsd:simpleType> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd new file mode 100644 index 0000000..687eea8 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd new file mode 100644 index 0000000..6ac81b0 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd @@ -0,0 +1,3081 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + xmlns="http://schemas.openxmlformats.org/drawingml/2006/main" + targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/main" + elementFormDefault="qualified"> + <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:import namespace="http://schemas.openxmlformats.org/drawingml/2006/diagram" + schemaLocation="dml-diagram.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/chart" + schemaLocation="dml-chart.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/picture" + schemaLocation="dml-picture.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" + schemaLocation="dml-lockedCanvas.xsd"/> + <xsd:complexType name="CT_AudioFile"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:link" use="required"/> + <xsd:attribute name="contentType" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_VideoFile"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:link" use="required"/> + <xsd:attribute name="contentType" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_QuickTimeFile"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:link" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AudioCDTime"> + <xsd:attribute name="track" type="xsd:unsignedByte" use="required"/> + <xsd:attribute name="time" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_AudioCD"> + <xsd:sequence> + <xsd:element name="st" type="CT_AudioCDTime" minOccurs="1" maxOccurs="1"/> + <xsd:element name="end" type="CT_AudioCDTime" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_Media"> + <xsd:choice> + <xsd:element name="audioCd" type="CT_AudioCD"/> + <xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/> + <xsd:element name="audioFile" type="CT_AudioFile"/> + <xsd:element name="videoFile" type="CT_VideoFile"/> + <xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/> + </xsd:choice> + </xsd:group> + <xsd:element name="videoFile" type="CT_VideoFile"/> + <xsd:simpleType name="ST_StyleMatrixColumnIndex"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_FontCollectionIndex"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="major"/> + <xsd:enumeration value="minor"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ColorSchemeIndex"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="dk1"/> + <xsd:enumeration value="lt1"/> + <xsd:enumeration value="dk2"/> + <xsd:enumeration value="lt2"/> + <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:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ColorScheme"> + <xsd:sequence> + <xsd:element name="dk1" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lt1" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="dk2" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lt2" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent1" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent2" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent3" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent4" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent5" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="accent6" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hlink" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="folHlink" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomColor"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_SupplementalFont"> + <xsd:attribute name="script" type="xsd:string" use="required"/> + <xsd:attribute name="typeface" type="ST_TextTypeface" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomColorList"> + <xsd:sequence> + <xsd:element name="custClr" type="CT_CustomColor" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FontCollection"> + <xsd:sequence> + <xsd:element name="latin" type="CT_TextFont" minOccurs="1" maxOccurs="1"/> + <xsd:element name="ea" type="CT_TextFont" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cs" type="CT_TextFont" minOccurs="1" maxOccurs="1"/> + <xsd:element name="font" type="CT_SupplementalFont" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EffectStyleItem"> + <xsd:sequence> + <xsd:group ref="EG_EffectProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FontScheme"> + <xsd:sequence> + <xsd:element name="majorFont" type="CT_FontCollection" minOccurs="1" maxOccurs="1"/> + <xsd:element name="minorFont" type="CT_FontCollection" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FillStyleList"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="3" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_LineStyleList"> + <xsd:sequence> + <xsd:element name="ln" type="CT_LineProperties" minOccurs="3" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EffectStyleList"> + <xsd:sequence> + <xsd:element name="effectStyle" type="CT_EffectStyleItem" minOccurs="3" maxOccurs="unbounded" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BackgroundFillStyleList"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="3" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StyleMatrix"> + <xsd:sequence> + <xsd:element name="fillStyleLst" type="CT_FillStyleList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lnStyleLst" type="CT_LineStyleList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="effectStyleLst" type="CT_EffectStyleList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="bgFillStyleLst" type="CT_BackgroundFillStyleList" minOccurs="1" + maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_BaseStyles"> + <xsd:sequence> + <xsd:element name="clrScheme" type="CT_ColorScheme" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fontScheme" type="CT_FontScheme" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fmtScheme" type="CT_StyleMatrix" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OfficeArtExtension"> + <xsd:sequence> + <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="xsd:token" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Coordinate"> + <xsd:union memberTypes="ST_CoordinateUnqualified s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:simpleType name="ST_CoordinateUnqualified"> + <xsd:restriction base="xsd:long"> + <xsd:minInclusive value="-27273042329600"/> + <xsd:maxInclusive value="27273042316900"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Coordinate32"> + <xsd:union memberTypes="ST_Coordinate32Unqualified s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Coordinate32Unqualified"> + <xsd:restriction base="xsd:int"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PositiveCoordinate"> + <xsd:restriction base="xsd:long"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="27273042316900"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PositiveCoordinate32"> + <xsd:restriction base="ST_Coordinate32Unqualified"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Angle"> + <xsd:restriction base="xsd:int"/> + </xsd:simpleType> + <xsd:complexType name="CT_Angle"> + <xsd:attribute name="val" type="ST_Angle" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_FixedAngle"> + <xsd:restriction base="ST_Angle"> + <xsd:minExclusive value="-5400000"/> + <xsd:maxExclusive value="5400000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PositiveFixedAngle"> + <xsd:restriction base="ST_Angle"> + <xsd:minInclusive value="0"/> + <xsd:maxExclusive value="21600000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PositiveFixedAngle"> + <xsd:attribute name="val" type="ST_PositiveFixedAngle" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Percentage"> + <xsd:union memberTypes="ST_PercentageDecimal s:ST_Percentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PercentageDecimal"> + <xsd:restriction base="xsd:int"/> + </xsd:simpleType> + <xsd:complexType name="CT_Percentage"> + <xsd:attribute name="val" type="ST_Percentage" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PositivePercentage"> + <xsd:union memberTypes="ST_PositivePercentageDecimal s:ST_PositivePercentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PositivePercentageDecimal"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PositivePercentage"> + <xsd:attribute name="val" type="ST_PositivePercentage" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_FixedPercentage"> + <xsd:union memberTypes="ST_FixedPercentageDecimal s:ST_FixedPercentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_FixedPercentageDecimal"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="-100000"/> + <xsd:maxInclusive value="100000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FixedPercentage"> + <xsd:attribute name="val" type="ST_FixedPercentage" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PositiveFixedPercentage"> + <xsd:union memberTypes="ST_PositiveFixedPercentageDecimal s:ST_PositiveFixedPercentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PositiveFixedPercentageDecimal"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="100000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PositiveFixedPercentage"> + <xsd:attribute name="val" type="ST_PositiveFixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Ratio"> + <xsd:attribute name="n" type="xsd:long" use="required"/> + <xsd:attribute name="d" type="xsd:long" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Point2D"> + <xsd:attribute name="x" type="ST_Coordinate" use="required"/> + <xsd:attribute name="y" type="ST_Coordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PositiveSize2D"> + <xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/> + <xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ComplementTransform"/> + <xsd:complexType name="CT_InverseTransform"/> + <xsd:complexType name="CT_GrayscaleTransform"/> + <xsd:complexType name="CT_GammaTransform"/> + <xsd:complexType name="CT_InverseGammaTransform"/> + <xsd:group name="EG_ColorTransform"> + <xsd:choice> + <xsd:element name="tint" type="CT_PositiveFixedPercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="shade" type="CT_PositiveFixedPercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="comp" type="CT_ComplementTransform" minOccurs="1" maxOccurs="1"/> + <xsd:element name="inv" type="CT_InverseTransform" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gray" type="CT_GrayscaleTransform" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alpha" type="CT_PositiveFixedPercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaOff" type="CT_FixedPercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaMod" type="CT_PositivePercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hue" type="CT_PositiveFixedAngle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hueOff" type="CT_Angle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hueMod" type="CT_PositivePercentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sat" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="satOff" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="satMod" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lum" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lumOff" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lumMod" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="red" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="redOff" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="redMod" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="green" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="greenOff" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="greenMod" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blue" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blueOff" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blueMod" type="CT_Percentage" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gamma" type="CT_GammaTransform" minOccurs="1" maxOccurs="1"/> + <xsd:element name="invGamma" type="CT_InverseGammaTransform" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_ScRgbColor"> + <xsd:sequence> + <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="r" type="ST_Percentage" use="required"/> + <xsd:attribute name="g" type="ST_Percentage" use="required"/> + <xsd:attribute name="b" type="ST_Percentage" use="required"/> + </xsd:complexType> + <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_HslColor"> + <xsd:sequence> + <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="hue" type="ST_PositiveFixedAngle" use="required"/> + <xsd:attribute name="sat" type="ST_Percentage" use="required"/> + <xsd:attribute name="lum" type="ST_Percentage" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_SystemColorVal"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="scrollBar"/> + <xsd:enumeration value="background"/> + <xsd:enumeration value="activeCaption"/> + <xsd:enumeration value="inactiveCaption"/> + <xsd:enumeration value="menu"/> + <xsd:enumeration value="window"/> + <xsd:enumeration value="windowFrame"/> + <xsd:enumeration value="menuText"/> + <xsd:enumeration value="windowText"/> + <xsd:enumeration value="captionText"/> + <xsd:enumeration value="activeBorder"/> + <xsd:enumeration value="inactiveBorder"/> + <xsd:enumeration value="appWorkspace"/> + <xsd:enumeration value="highlight"/> + <xsd:enumeration value="highlightText"/> + <xsd:enumeration value="btnFace"/> + <xsd:enumeration value="btnShadow"/> + <xsd:enumeration value="grayText"/> + <xsd:enumeration value="btnText"/> + <xsd:enumeration value="inactiveCaptionText"/> + <xsd:enumeration value="btnHighlight"/> + <xsd:enumeration value="3dDkShadow"/> + <xsd:enumeration value="3dLight"/> + <xsd:enumeration value="infoText"/> + <xsd:enumeration value="infoBk"/> + <xsd:enumeration value="hotLight"/> + <xsd:enumeration value="gradientActiveCaption"/> + <xsd:enumeration value="gradientInactiveCaption"/> + <xsd:enumeration value="menuHighlight"/> + <xsd:enumeration value="menuBar"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SystemColor"> + <xsd:sequence> + <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="val" type="ST_SystemColorVal" use="required"/> + <xsd:attribute name="lastClr" type="s:ST_HexColorRGB" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_SchemeColorVal"> + <xsd:restriction base="xsd:token"> + <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="phClr"/> + <xsd:enumeration value="dk1"/> + <xsd:enumeration value="lt1"/> + <xsd:enumeration value="dk2"/> + <xsd:enumeration value="lt2"/> + </xsd:restriction> + </xsd:simpleType> + <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:simpleType name="ST_PresetColorVal"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="aliceBlue"/> + <xsd:enumeration value="antiqueWhite"/> + <xsd:enumeration value="aqua"/> + <xsd:enumeration value="aquamarine"/> + <xsd:enumeration value="azure"/> + <xsd:enumeration value="beige"/> + <xsd:enumeration value="bisque"/> + <xsd:enumeration value="black"/> + <xsd:enumeration value="blanchedAlmond"/> + <xsd:enumeration value="blue"/> + <xsd:enumeration value="blueViolet"/> + <xsd:enumeration value="brown"/> + <xsd:enumeration value="burlyWood"/> + <xsd:enumeration value="cadetBlue"/> + <xsd:enumeration value="chartreuse"/> + <xsd:enumeration value="chocolate"/> + <xsd:enumeration value="coral"/> + <xsd:enumeration value="cornflowerBlue"/> + <xsd:enumeration value="cornsilk"/> + <xsd:enumeration value="crimson"/> + <xsd:enumeration value="cyan"/> + <xsd:enumeration value="darkBlue"/> + <xsd:enumeration value="darkCyan"/> + <xsd:enumeration value="darkGoldenrod"/> + <xsd:enumeration value="darkGray"/> + <xsd:enumeration value="darkGrey"/> + <xsd:enumeration value="darkGreen"/> + <xsd:enumeration value="darkKhaki"/> + <xsd:enumeration value="darkMagenta"/> + <xsd:enumeration value="darkOliveGreen"/> + <xsd:enumeration value="darkOrange"/> + <xsd:enumeration value="darkOrchid"/> + <xsd:enumeration value="darkRed"/> + <xsd:enumeration value="darkSalmon"/> + <xsd:enumeration value="darkSeaGreen"/> + <xsd:enumeration value="darkSlateBlue"/> + <xsd:enumeration value="darkSlateGray"/> + <xsd:enumeration value="darkSlateGrey"/> + <xsd:enumeration value="darkTurquoise"/> + <xsd:enumeration value="darkViolet"/> + <xsd:enumeration value="dkBlue"/> + <xsd:enumeration value="dkCyan"/> + <xsd:enumeration value="dkGoldenrod"/> + <xsd:enumeration value="dkGray"/> + <xsd:enumeration value="dkGrey"/> + <xsd:enumeration value="dkGreen"/> + <xsd:enumeration value="dkKhaki"/> + <xsd:enumeration value="dkMagenta"/> + <xsd:enumeration value="dkOliveGreen"/> + <xsd:enumeration value="dkOrange"/> + <xsd:enumeration value="dkOrchid"/> + <xsd:enumeration value="dkRed"/> + <xsd:enumeration value="dkSalmon"/> + <xsd:enumeration value="dkSeaGreen"/> + <xsd:enumeration value="dkSlateBlue"/> + <xsd:enumeration value="dkSlateGray"/> + <xsd:enumeration value="dkSlateGrey"/> + <xsd:enumeration value="dkTurquoise"/> + <xsd:enumeration value="dkViolet"/> + <xsd:enumeration value="deepPink"/> + <xsd:enumeration value="deepSkyBlue"/> + <xsd:enumeration value="dimGray"/> + <xsd:enumeration value="dimGrey"/> + <xsd:enumeration value="dodgerBlue"/> + <xsd:enumeration value="firebrick"/> + <xsd:enumeration value="floralWhite"/> + <xsd:enumeration value="forestGreen"/> + <xsd:enumeration value="fuchsia"/> + <xsd:enumeration value="gainsboro"/> + <xsd:enumeration value="ghostWhite"/> + <xsd:enumeration value="gold"/> + <xsd:enumeration value="goldenrod"/> + <xsd:enumeration value="gray"/> + <xsd:enumeration value="grey"/> + <xsd:enumeration value="green"/> + <xsd:enumeration value="greenYellow"/> + <xsd:enumeration value="honeydew"/> + <xsd:enumeration value="hotPink"/> + <xsd:enumeration value="indianRed"/> + <xsd:enumeration value="indigo"/> + <xsd:enumeration value="ivory"/> + <xsd:enumeration value="khaki"/> + <xsd:enumeration value="lavender"/> + <xsd:enumeration value="lavenderBlush"/> + <xsd:enumeration value="lawnGreen"/> + <xsd:enumeration value="lemonChiffon"/> + <xsd:enumeration value="lightBlue"/> + <xsd:enumeration value="lightCoral"/> + <xsd:enumeration value="lightCyan"/> + <xsd:enumeration value="lightGoldenrodYellow"/> + <xsd:enumeration value="lightGray"/> + <xsd:enumeration value="lightGrey"/> + <xsd:enumeration value="lightGreen"/> + <xsd:enumeration value="lightPink"/> + <xsd:enumeration value="lightSalmon"/> + <xsd:enumeration value="lightSeaGreen"/> + <xsd:enumeration value="lightSkyBlue"/> + <xsd:enumeration value="lightSlateGray"/> + <xsd:enumeration value="lightSlateGrey"/> + <xsd:enumeration value="lightSteelBlue"/> + <xsd:enumeration value="lightYellow"/> + <xsd:enumeration value="ltBlue"/> + <xsd:enumeration value="ltCoral"/> + <xsd:enumeration value="ltCyan"/> + <xsd:enumeration value="ltGoldenrodYellow"/> + <xsd:enumeration value="ltGray"/> + <xsd:enumeration value="ltGrey"/> + <xsd:enumeration value="ltGreen"/> + <xsd:enumeration value="ltPink"/> + <xsd:enumeration value="ltSalmon"/> + <xsd:enumeration value="ltSeaGreen"/> + <xsd:enumeration value="ltSkyBlue"/> + <xsd:enumeration value="ltSlateGray"/> + <xsd:enumeration value="ltSlateGrey"/> + <xsd:enumeration value="ltSteelBlue"/> + <xsd:enumeration value="ltYellow"/> + <xsd:enumeration value="lime"/> + <xsd:enumeration value="limeGreen"/> + <xsd:enumeration value="linen"/> + <xsd:enumeration value="magenta"/> + <xsd:enumeration value="maroon"/> + <xsd:enumeration value="medAquamarine"/> + <xsd:enumeration value="medBlue"/> + <xsd:enumeration value="medOrchid"/> + <xsd:enumeration value="medPurple"/> + <xsd:enumeration value="medSeaGreen"/> + <xsd:enumeration value="medSlateBlue"/> + <xsd:enumeration value="medSpringGreen"/> + <xsd:enumeration value="medTurquoise"/> + <xsd:enumeration value="medVioletRed"/> + <xsd:enumeration value="mediumAquamarine"/> + <xsd:enumeration value="mediumBlue"/> + <xsd:enumeration value="mediumOrchid"/> + <xsd:enumeration value="mediumPurple"/> + <xsd:enumeration value="mediumSeaGreen"/> + <xsd:enumeration value="mediumSlateBlue"/> + <xsd:enumeration value="mediumSpringGreen"/> + <xsd:enumeration value="mediumTurquoise"/> + <xsd:enumeration value="mediumVioletRed"/> + <xsd:enumeration value="midnightBlue"/> + <xsd:enumeration value="mintCream"/> + <xsd:enumeration value="mistyRose"/> + <xsd:enumeration value="moccasin"/> + <xsd:enumeration value="navajoWhite"/> + <xsd:enumeration value="navy"/> + <xsd:enumeration value="oldLace"/> + <xsd:enumeration value="olive"/> + <xsd:enumeration value="oliveDrab"/> + <xsd:enumeration value="orange"/> + <xsd:enumeration value="orangeRed"/> + <xsd:enumeration value="orchid"/> + <xsd:enumeration value="paleGoldenrod"/> + <xsd:enumeration value="paleGreen"/> + <xsd:enumeration value="paleTurquoise"/> + <xsd:enumeration value="paleVioletRed"/> + <xsd:enumeration value="papayaWhip"/> + <xsd:enumeration value="peachPuff"/> + <xsd:enumeration value="peru"/> + <xsd:enumeration value="pink"/> + <xsd:enumeration value="plum"/> + <xsd:enumeration value="powderBlue"/> + <xsd:enumeration value="purple"/> + <xsd:enumeration value="red"/> + <xsd:enumeration value="rosyBrown"/> + <xsd:enumeration value="royalBlue"/> + <xsd:enumeration value="saddleBrown"/> + <xsd:enumeration value="salmon"/> + <xsd:enumeration value="sandyBrown"/> + <xsd:enumeration value="seaGreen"/> + <xsd:enumeration value="seaShell"/> + <xsd:enumeration value="sienna"/> + <xsd:enumeration value="silver"/> + <xsd:enumeration value="skyBlue"/> + <xsd:enumeration value="slateBlue"/> + <xsd:enumeration value="slateGray"/> + <xsd:enumeration value="slateGrey"/> + <xsd:enumeration value="snow"/> + <xsd:enumeration value="springGreen"/> + <xsd:enumeration value="steelBlue"/> + <xsd:enumeration value="tan"/> + <xsd:enumeration value="teal"/> + <xsd:enumeration value="thistle"/> + <xsd:enumeration value="tomato"/> + <xsd:enumeration value="turquoise"/> + <xsd:enumeration value="violet"/> + <xsd:enumeration value="wheat"/> + <xsd:enumeration value="white"/> + <xsd:enumeration value="whiteSmoke"/> + <xsd:enumeration value="yellow"/> + <xsd:enumeration value="yellowGreen"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PresetColor"> + <xsd:sequence> + <xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="val" type="ST_PresetColorVal" use="required"/> + </xsd:complexType> + <xsd:group name="EG_OfficeArtExtensionList"> + <xsd:sequence> + <xsd:element name="ext" type="CT_OfficeArtExtension" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_OfficeArtExtensionList"> + <xsd:sequence> + <xsd:group ref="EG_OfficeArtExtensionList" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Scale2D"> + <xsd:sequence> + <xsd:element name="sx" type="CT_Ratio" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sy" type="CT_Ratio" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Transform2D"> + <xsd:sequence> + <xsd:element name="off" type="CT_Point2D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rot" type="ST_Angle" use="optional" default="0"/> + <xsd:attribute name="flipH" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="flipV" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupTransform2D"> + <xsd:sequence> + <xsd:element name="off" type="CT_Point2D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="chOff" type="CT_Point2D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="chExt" type="CT_PositiveSize2D" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rot" type="ST_Angle" use="optional" default="0"/> + <xsd:attribute name="flipH" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="flipV" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Point3D"> + <xsd:attribute name="x" type="ST_Coordinate" use="required"/> + <xsd:attribute name="y" type="ST_Coordinate" use="required"/> + <xsd:attribute name="z" type="ST_Coordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Vector3D"> + <xsd:attribute name="dx" type="ST_Coordinate" use="required"/> + <xsd:attribute name="dy" type="ST_Coordinate" use="required"/> + <xsd:attribute name="dz" type="ST_Coordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SphereCoords"> + <xsd:attribute name="lat" type="ST_PositiveFixedAngle" use="required"/> + <xsd:attribute name="lon" type="ST_PositiveFixedAngle" use="required"/> + <xsd:attribute name="rev" type="ST_PositiveFixedAngle" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RelativeRect"> + <xsd:attribute name="l" type="ST_Percentage" use="optional" default="0%"/> + <xsd:attribute name="t" type="ST_Percentage" use="optional" default="0%"/> + <xsd:attribute name="r" type="ST_Percentage" use="optional" default="0%"/> + <xsd:attribute name="b" type="ST_Percentage" use="optional" default="0%"/> + </xsd:complexType> + <xsd:simpleType name="ST_RectAlignment"> + <xsd:restriction base="xsd:token"> + <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:group name="EG_ColorChoice"> + <xsd:choice> + <xsd:element name="scrgbClr" type="CT_ScRgbColor" minOccurs="1" maxOccurs="1"/> + <xsd:element name="srgbClr" type="CT_SRgbColor" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hslClr" type="CT_HslColor" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sysClr" type="CT_SystemColor" minOccurs="1" maxOccurs="1"/> + <xsd:element name="schemeClr" type="CT_SchemeColor" minOccurs="1" maxOccurs="1"/> + <xsd:element name="prstClr" type="CT_PresetColor" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_Color"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ColorMRU"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_BlackWhiteMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="clr"/> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="gray"/> + <xsd:enumeration value="ltGray"/> + <xsd:enumeration value="invGray"/> + <xsd:enumeration value="grayWhite"/> + <xsd:enumeration value="blackGray"/> + <xsd:enumeration value="blackWhite"/> + <xsd:enumeration value="black"/> + <xsd:enumeration value="white"/> + <xsd:enumeration value="hidden"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:attributeGroup name="AG_Blob"> + <xsd:attribute ref="r:embed" use="optional" default=""/> + <xsd:attribute ref="r:link" use="optional" default=""/> + </xsd:attributeGroup> + <xsd:complexType name="CT_EmbeddedWAVAudioFile"> + <xsd:attribute ref="r:embed" use="required"/> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_Hyperlink"> + <xsd:sequence> + <xsd:element name="snd" type="CT_EmbeddedWAVAudioFile" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="optional"/> + <xsd:attribute name="invalidUrl" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="action" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="tgtFrame" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="tooltip" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="history" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="highlightClick" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="endSnd" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_DrawingElementId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:attributeGroup name="AG_Locking"> + <xsd:attribute name="noGrp" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noSelect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noRot" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noChangeAspect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noMove" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noResize" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noEditPoints" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noAdjustHandles" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noChangeArrowheads" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noChangeShapeType" type="xsd:boolean" use="optional" default="false"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_ConnectorLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Locking"/> + </xsd:complexType> + <xsd:complexType name="CT_ShapeLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Locking"/> + <xsd:attribute name="noTextEdit" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_PictureLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Locking"/> + <xsd:attribute name="noCrop" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="noGrp" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noUngrp" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noSelect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noRot" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noChangeAspect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noMove" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noResize" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_GraphicalObjectFrameLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="noGrp" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noDrilldown" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noSelect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noChangeAspect" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noMove" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="noResize" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ContentPartLocking"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Locking"/> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualDrawingProps"> + <xsd:sequence> + <xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hlinkHover" type="CT_Hyperlink" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_DrawingElementId" use="required"/> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="descr" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="title" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualDrawingShapeProps"> + <xsd:sequence> + <xsd:element name="spLocks" type="CT_ShapeLocking" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="txBox" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualConnectorProperties"> + <xsd:sequence> + <xsd:element name="cxnSpLocks" type="CT_ConnectorLocking" minOccurs="0" maxOccurs="1"/> + <xsd:element name="stCxn" type="CT_Connection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="endCxn" type="CT_Connection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualPictureProperties"> + <xsd:sequence> + <xsd:element name="picLocks" type="CT_PictureLocking" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="preferRelativeResize" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualGroupDrawingShapeProps"> + <xsd:sequence> + <xsd:element name="grpSpLocks" type="CT_GroupLocking" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualGraphicFrameProperties"> + <xsd:sequence> + <xsd:element name="graphicFrameLocks" type="CT_GraphicalObjectFrameLocking" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NonVisualContentPartProperties"> + <xsd:sequence> + <xsd:element name="cpLocks" type="CT_ContentPartLocking" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="isComment" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_GraphicalObjectData"> + <xsd:sequence> + <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="strict"/> + </xsd:sequence> + <xsd:attribute name="uri" type="xsd:token" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_GraphicalObject"> + <xsd:sequence> + <xsd:element name="graphicData" type="CT_GraphicalObjectData"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="graphic" type="CT_GraphicalObject"/> + <xsd:simpleType name="ST_ChartBuildStep"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="category"/> + <xsd:enumeration value="ptInCategory"/> + <xsd:enumeration value="series"/> + <xsd:enumeration value="ptInSeries"/> + <xsd:enumeration value="allPts"/> + <xsd:enumeration value="gridLegend"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DgmBuildStep"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sp"/> + <xsd:enumeration value="bg"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_AnimationDgmElement"> + <xsd:attribute name="id" type="s:ST_Guid" use="optional" + default="{00000000-0000-0000-0000-000000000000}"/> + <xsd:attribute name="bldStep" type="ST_DgmBuildStep" use="optional" default="sp"/> + </xsd:complexType> + <xsd:complexType name="CT_AnimationChartElement"> + <xsd:attribute name="seriesIdx" type="xsd:int" use="optional" default="-1"/> + <xsd:attribute name="categoryIdx" type="xsd:int" use="optional" default="-1"/> + <xsd:attribute name="bldStep" type="ST_ChartBuildStep" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AnimationElementChoice"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="dgm" type="CT_AnimationDgmElement"/> + <xsd:element name="chart" type="CT_AnimationChartElement"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_AnimationBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="allAtOnce"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnimationDgmOnlyBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="one"/> + <xsd:enumeration value="lvlOne"/> + <xsd:enumeration value="lvlAtOnce"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnimationDgmBuildType"> + <xsd:union memberTypes="ST_AnimationBuildType ST_AnimationDgmOnlyBuildType"/> + </xsd:simpleType> + <xsd:complexType name="CT_AnimationDgmBuildProperties"> + <xsd:attribute name="bld" type="ST_AnimationDgmBuildType" use="optional" default="allAtOnce"/> + <xsd:attribute name="rev" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_AnimationChartOnlyBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="series"/> + <xsd:enumeration value="category"/> + <xsd:enumeration value="seriesEl"/> + <xsd:enumeration value="categoryEl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnimationChartBuildType"> + <xsd:union memberTypes="ST_AnimationBuildType ST_AnimationChartOnlyBuildType"/> + </xsd:simpleType> + <xsd:complexType name="CT_AnimationChartBuildProperties"> + <xsd:attribute name="bld" type="ST_AnimationChartBuildType" use="optional" default="allAtOnce"/> + <xsd:attribute name="animBg" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_AnimationGraphicalObjectBuildProperties"> + <xsd:choice> + <xsd:element name="bldDgm" type="CT_AnimationDgmBuildProperties"/> + <xsd:element name="bldChart" type="CT_AnimationChartBuildProperties"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_BackgroundFormatting"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_WholeE2oFormatting"> + <xsd:sequence> + <xsd:element name="ln" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlUseShapeRectangle"/> + <xsd:complexType name="CT_GvmlTextShape"> + <xsd:sequence> + <xsd:element name="txBody" type="CT_TextBody" minOccurs="1" maxOccurs="1"/> + <xsd:choice> + <xsd:element name="useSpRect" type="CT_GvmlUseShapeRectangle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="xfrm" type="CT_Transform2D" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlShapeNonVisual"> + <xsd:sequence> + <xsd:element name="cNvPr" type="CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cNvSpPr" type="CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlShape"> + <xsd:sequence> + <xsd:element name="nvSpPr" type="CT_GvmlShapeNonVisual" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="txSp" type="CT_GvmlTextShape" minOccurs="0" maxOccurs="1"/> + <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlConnectorNonVisual"> + <xsd:sequence> + <xsd:element name="cNvPr" type="CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cNvCxnSpPr" type="CT_NonVisualConnectorProperties" minOccurs="1" + maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlConnector"> + <xsd:sequence> + <xsd:element name="nvCxnSpPr" type="CT_GvmlConnectorNonVisual" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlPictureNonVisual"> + <xsd:sequence> + <xsd:element name="cNvPr" type="CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cNvPicPr" type="CT_NonVisualPictureProperties" minOccurs="1" maxOccurs="1" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlPicture"> + <xsd:sequence> + <xsd:element name="nvPicPr" type="CT_GvmlPictureNonVisual" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blipFill" type="CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlGraphicFrameNonVisual"> + <xsd:sequence> + <xsd:element name="cNvPr" type="CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cNvGraphicFramePr" type="CT_NonVisualGraphicFrameProperties" minOccurs="1" + maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlGraphicalObjectFrame"> + <xsd:sequence> + <xsd:element name="nvGraphicFramePr" type="CT_GvmlGraphicFrameNonVisual" minOccurs="1" + maxOccurs="1"/> + <xsd:element ref="graphic" minOccurs="1" maxOccurs="1"/> + <xsd:element name="xfrm" type="CT_Transform2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlGroupShapeNonVisual"> + <xsd:sequence> + <xsd:element name="cNvPr" type="CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cNvGrpSpPr" type="CT_NonVisualGroupDrawingShapeProps" minOccurs="1" + maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GvmlGroupShape"> + <xsd:sequence> + <xsd:element name="nvGrpSpPr" type="CT_GvmlGroupShapeNonVisual" minOccurs="1" maxOccurs="1"/> + <xsd:element name="grpSpPr" type="CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="txSp" type="CT_GvmlTextShape"/> + <xsd:element name="sp" type="CT_GvmlShape"/> + <xsd:element name="cxnSp" type="CT_GvmlConnector"/> + <xsd:element name="pic" type="CT_GvmlPicture"/> + <xsd:element name="graphicFrame" type="CT_GvmlGraphicalObjectFrame"/> + <xsd:element name="grpSp" type="CT_GvmlGroupShape"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <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:simpleType name="ST_FOVAngle"> + <xsd:restriction base="ST_Angle"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="10800000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Camera"> + <xsd:sequence> + <xsd:element name="rot" type="CT_SphereCoords" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prst" type="ST_PresetCameraType" use="required"/> + <xsd:attribute name="fov" type="ST_FOVAngle" use="optional"/> + <xsd:attribute name="zoom" type="ST_PositivePercentage" use="optional" default="100%"/> + </xsd:complexType> + <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: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:complexType name="CT_LightRig"> + <xsd:sequence> + <xsd:element name="rot" type="CT_SphereCoords" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rig" type="ST_LightRigType" use="required"/> + <xsd:attribute name="dir" type="ST_LightRigDirection" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Scene3D"> + <xsd:sequence> + <xsd:element name="camera" type="CT_Camera" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lightRig" type="CT_LightRig" minOccurs="1" maxOccurs="1"/> + <xsd:element name="backdrop" type="CT_Backdrop" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Backdrop"> + <xsd:sequence> + <xsd:element name="anchor" type="CT_Point3D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="norm" type="CT_Vector3D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="up" type="CT_Vector3D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </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="ST_PositiveCoordinate" use="optional" default="76200"/> + <xsd:attribute name="h" type="ST_PositiveCoordinate" use="optional" default="76200"/> + <xsd:attribute name="prst" type="ST_BevelPresetType" use="optional" default="circle"/> + </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:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Shape3D"> + <xsd:sequence> + <xsd:element name="bevelT" type="CT_Bevel" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bevelB" type="CT_Bevel" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extrusionClr" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="contourClr" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="z" type="ST_Coordinate" use="optional" default="0"/> + <xsd:attribute name="extrusionH" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="contourW" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="prstMaterial" type="ST_PresetMaterialType" use="optional" + default="warmMatte"/> + </xsd:complexType> + <xsd:complexType name="CT_FlatText"> + <xsd:attribute name="z" type="ST_Coordinate" use="optional" default="0"/> + </xsd:complexType> + <xsd:group name="EG_Text3D"> + <xsd:choice> + <xsd:element name="sp3d" type="CT_Shape3D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="flatTx" type="CT_FlatText" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_AlphaBiLevelEffect"> + <xsd:attribute name="thresh" type="ST_PositiveFixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AlphaCeilingEffect"/> + <xsd:complexType name="CT_AlphaFloorEffect"/> + <xsd:complexType name="CT_AlphaInverseEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_AlphaModulateFixedEffect"> + <xsd:attribute name="amt" type="ST_PositivePercentage" use="optional" default="100%"/> + </xsd:complexType> + <xsd:complexType name="CT_AlphaOutsetEffect"> + <xsd:attribute name="rad" type="ST_Coordinate" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_AlphaReplaceEffect"> + <xsd:attribute name="a" type="ST_PositiveFixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_BiLevelEffect"> + <xsd:attribute name="thresh" type="ST_PositiveFixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_BlurEffect"> + <xsd:attribute name="rad" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="grow" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_ColorChangeEffect"> + <xsd:sequence> + <xsd:element name="clrFrom" type="CT_Color" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrTo" type="CT_Color" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="useA" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_ColorReplaceEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DuotoneEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="2" maxOccurs="2"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GlowEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rad" type="ST_PositiveCoordinate" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_GrayscaleEffect"/> + <xsd:complexType name="CT_HSLEffect"> + <xsd:attribute name="hue" type="ST_PositiveFixedAngle" use="optional" default="0"/> + <xsd:attribute name="sat" type="ST_FixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="lum" type="ST_FixedPercentage" use="optional" default="0%"/> + </xsd:complexType> + <xsd:complexType name="CT_InnerShadowEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="blurRad" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dist" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dir" type="ST_PositiveFixedAngle" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_LuminanceEffect"> + <xsd:attribute name="bright" type="ST_FixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="contrast" type="ST_FixedPercentage" use="optional" default="0%"/> + </xsd:complexType> + <xsd:complexType name="CT_OuterShadowEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="blurRad" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dist" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dir" type="ST_PositiveFixedAngle" use="optional" default="0"/> + <xsd:attribute name="sx" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="sy" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="kx" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="ky" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="algn" type="ST_RectAlignment" use="optional" default="b"/> + <xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:simpleType name="ST_PresetShadowVal"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="shdw1"/> + <xsd:enumeration value="shdw2"/> + <xsd:enumeration value="shdw3"/> + <xsd:enumeration value="shdw4"/> + <xsd:enumeration value="shdw5"/> + <xsd:enumeration value="shdw6"/> + <xsd:enumeration value="shdw7"/> + <xsd:enumeration value="shdw8"/> + <xsd:enumeration value="shdw9"/> + <xsd:enumeration value="shdw10"/> + <xsd:enumeration value="shdw11"/> + <xsd:enumeration value="shdw12"/> + <xsd:enumeration value="shdw13"/> + <xsd:enumeration value="shdw14"/> + <xsd:enumeration value="shdw15"/> + <xsd:enumeration value="shdw16"/> + <xsd:enumeration value="shdw17"/> + <xsd:enumeration value="shdw18"/> + <xsd:enumeration value="shdw19"/> + <xsd:enumeration value="shdw20"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PresetShadowEffect"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prst" type="ST_PresetShadowVal" use="required"/> + <xsd:attribute name="dist" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dir" type="ST_PositiveFixedAngle" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_ReflectionEffect"> + <xsd:attribute name="blurRad" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="stA" type="ST_PositiveFixedPercentage" use="optional" default="100%"/> + <xsd:attribute name="stPos" type="ST_PositiveFixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="endA" type="ST_PositiveFixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="endPos" type="ST_PositiveFixedPercentage" use="optional" default="100%"/> + <xsd:attribute name="dist" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="dir" type="ST_PositiveFixedAngle" use="optional" default="0"/> + <xsd:attribute name="fadeDir" type="ST_PositiveFixedAngle" use="optional" default="5400000"/> + <xsd:attribute name="sx" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="sy" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="kx" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="ky" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="algn" type="ST_RectAlignment" use="optional" default="b"/> + <xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_RelativeOffsetEffect"> + <xsd:attribute name="tx" type="ST_Percentage" use="optional" default="0%"/> + <xsd:attribute name="ty" type="ST_Percentage" use="optional" default="0%"/> + </xsd:complexType> + <xsd:complexType name="CT_SoftEdgesEffect"> + <xsd:attribute name="rad" type="ST_PositiveCoordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TintEffect"> + <xsd:attribute name="hue" type="ST_PositiveFixedAngle" use="optional" default="0"/> + <xsd:attribute name="amt" type="ST_FixedPercentage" use="optional" default="0%"/> + </xsd:complexType> + <xsd:complexType name="CT_TransformEffect"> + <xsd:attribute name="sx" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="sy" type="ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="kx" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="ky" type="ST_FixedAngle" use="optional" default="0"/> + <xsd:attribute name="tx" type="ST_Coordinate" use="optional" default="0"/> + <xsd:attribute name="ty" type="ST_Coordinate" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_NoFillProperties"/> + <xsd:complexType name="CT_SolidColorFillProperties"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_LinearShadeProperties"> + <xsd:attribute name="ang" type="ST_PositiveFixedAngle" use="optional"/> + <xsd:attribute name="scaled" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PathShadeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="shape"/> + <xsd:enumeration value="circle"/> + <xsd:enumeration value="rect"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PathShadeProperties"> + <xsd:sequence> + <xsd:element name="fillToRect" type="CT_RelativeRect" minOccurs="0" maxOccurs="1"/> + </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" minOccurs="1" maxOccurs="1"/> + <xsd:element name="path" type="CT_PathShadeProperties" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_TileFlipMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="x"/> + <xsd:enumeration value="y"/> + <xsd:enumeration value="xy"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_GradientStop"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="pos" type="ST_PositiveFixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_GradientStopList"> + <xsd:sequence> + <xsd:element name="gs" type="CT_GradientStop" minOccurs="2" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_GradientFillProperties"> + <xsd:sequence> + <xsd:element name="gsLst" type="CT_GradientStopList" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ShadeProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tileRect" type="CT_RelativeRect" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="flip" type="ST_TileFlipMode" use="optional" default="none"/> + <xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TileInfoProperties"> + <xsd:attribute name="tx" type="ST_Coordinate" use="optional"/> + <xsd:attribute name="ty" type="ST_Coordinate" use="optional"/> + <xsd:attribute name="sx" type="ST_Percentage" use="optional"/> + <xsd:attribute name="sy" type="ST_Percentage" use="optional"/> + <xsd:attribute name="flip" type="ST_TileFlipMode" use="optional" default="none"/> + <xsd:attribute name="algn" type="ST_RectAlignment" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_StretchInfoProperties"> + <xsd:sequence> + <xsd:element name="fillRect" type="CT_RelativeRect" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_FillModeProperties"> + <xsd:choice> + <xsd:element name="tile" type="CT_TileInfoProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="stretch" type="CT_StretchInfoProperties" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_BlipCompression"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="email"/> + <xsd:enumeration value="screen"/> + <xsd:enumeration value="print"/> + <xsd:enumeration value="hqprint"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Blip"> + <xsd:sequence> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="alphaBiLevel" type="CT_AlphaBiLevelEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaCeiling" type="CT_AlphaCeilingEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaFloor" type="CT_AlphaFloorEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaInv" type="CT_AlphaInverseEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaMod" type="CT_AlphaModulateEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaModFix" type="CT_AlphaModulateFixedEffect" minOccurs="1" + maxOccurs="1"/> + <xsd:element name="alphaRepl" type="CT_AlphaReplaceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="biLevel" type="CT_BiLevelEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blur" type="CT_BlurEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrChange" type="CT_ColorChangeEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrRepl" type="CT_ColorReplaceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="duotone" type="CT_DuotoneEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fillOverlay" type="CT_FillOverlayEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="grayscl" type="CT_GrayscaleEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hsl" type="CT_HSLEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lum" type="CT_LuminanceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tint" type="CT_TintEffect" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Blob"/> + <xsd:attribute name="cstate" type="ST_BlipCompression" use="optional" default="none"/> + </xsd:complexType> + <xsd:complexType name="CT_BlipFillProperties"> + <xsd:sequence> + <xsd:element name="blip" type="CT_Blip" minOccurs="0" maxOccurs="1"/> + <xsd:element name="srcRect" type="CT_RelativeRect" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_FillModeProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="dpi" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PresetPatternVal"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pct5"/> + <xsd:enumeration value="pct10"/> + <xsd:enumeration value="pct20"/> + <xsd:enumeration value="pct25"/> + <xsd:enumeration value="pct30"/> + <xsd:enumeration value="pct40"/> + <xsd:enumeration value="pct50"/> + <xsd:enumeration value="pct60"/> + <xsd:enumeration value="pct70"/> + <xsd:enumeration value="pct75"/> + <xsd:enumeration value="pct80"/> + <xsd:enumeration value="pct90"/> + <xsd:enumeration value="horz"/> + <xsd:enumeration value="vert"/> + <xsd:enumeration value="ltHorz"/> + <xsd:enumeration value="ltVert"/> + <xsd:enumeration value="dkHorz"/> + <xsd:enumeration value="dkVert"/> + <xsd:enumeration value="narHorz"/> + <xsd:enumeration value="narVert"/> + <xsd:enumeration value="dashHorz"/> + <xsd:enumeration value="dashVert"/> + <xsd:enumeration value="cross"/> + <xsd:enumeration value="dnDiag"/> + <xsd:enumeration value="upDiag"/> + <xsd:enumeration value="ltDnDiag"/> + <xsd:enumeration value="ltUpDiag"/> + <xsd:enumeration value="dkDnDiag"/> + <xsd:enumeration value="dkUpDiag"/> + <xsd:enumeration value="wdDnDiag"/> + <xsd:enumeration value="wdUpDiag"/> + <xsd:enumeration value="dashDnDiag"/> + <xsd:enumeration value="dashUpDiag"/> + <xsd:enumeration value="diagCross"/> + <xsd:enumeration value="smCheck"/> + <xsd:enumeration value="lgCheck"/> + <xsd:enumeration value="smGrid"/> + <xsd:enumeration value="lgGrid"/> + <xsd:enumeration value="dotGrid"/> + <xsd:enumeration value="smConfetti"/> + <xsd:enumeration value="lgConfetti"/> + <xsd:enumeration value="horzBrick"/> + <xsd:enumeration value="diagBrick"/> + <xsd:enumeration value="solidDmnd"/> + <xsd:enumeration value="openDmnd"/> + <xsd:enumeration value="dotDmnd"/> + <xsd:enumeration value="plaid"/> + <xsd:enumeration value="sphere"/> + <xsd:enumeration value="weave"/> + <xsd:enumeration value="divot"/> + <xsd:enumeration value="shingle"/> + <xsd:enumeration value="wave"/> + <xsd:enumeration value="trellis"/> + <xsd:enumeration value="zigZag"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PatternFillProperties"> + <xsd:sequence> + <xsd:element name="fgClr" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bgClr" type="CT_Color" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prst" type="ST_PresetPatternVal" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupFillProperties"/> + <xsd:group name="EG_FillProperties"> + <xsd:choice> + <xsd:element name="noFill" type="CT_NoFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="solidFill" type="CT_SolidColorFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gradFill" type="CT_GradientFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blipFill" type="CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="pattFill" type="CT_PatternFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="grpFill" type="CT_GroupFillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_FillProperties"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FillEffect"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_BlendMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="over"/> + <xsd:enumeration value="mult"/> + <xsd:enumeration value="screen"/> + <xsd:enumeration value="darken"/> + <xsd:enumeration value="lighten"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FillOverlayEffect"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="blend" type="ST_BlendMode" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_EffectReference"> + <xsd:attribute name="ref" type="xsd:token" use="required"/> + </xsd:complexType> + <xsd:group name="EG_Effect"> + <xsd:choice> + <xsd:element name="cont" type="CT_EffectContainer" minOccurs="1" maxOccurs="1"/> + <xsd:element name="effect" type="CT_EffectReference" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaBiLevel" type="CT_AlphaBiLevelEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaCeiling" type="CT_AlphaCeilingEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaFloor" type="CT_AlphaFloorEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaInv" type="CT_AlphaInverseEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaMod" type="CT_AlphaModulateEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaModFix" type="CT_AlphaModulateFixedEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaOutset" type="CT_AlphaOutsetEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="alphaRepl" type="CT_AlphaReplaceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="biLevel" type="CT_BiLevelEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blend" type="CT_BlendEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="blur" type="CT_BlurEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrChange" type="CT_ColorChangeEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrRepl" type="CT_ColorReplaceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="duotone" type="CT_DuotoneEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fill" type="CT_FillEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fillOverlay" type="CT_FillOverlayEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="glow" type="CT_GlowEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="grayscl" type="CT_GrayscaleEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hsl" type="CT_HSLEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="innerShdw" type="CT_InnerShadowEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lum" type="CT_LuminanceEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="outerShdw" type="CT_OuterShadowEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="prstShdw" type="CT_PresetShadowEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="reflection" type="CT_ReflectionEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="relOff" type="CT_RelativeOffsetEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="softEdge" type="CT_SoftEdgesEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tint" type="CT_TintEffect" minOccurs="1" maxOccurs="1"/> + <xsd:element name="xfrm" type="CT_TransformEffect" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_EffectContainerType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sib"/> + <xsd:enumeration value="tree"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_EffectContainer"> + <xsd:group ref="EG_Effect" minOccurs="0" maxOccurs="unbounded"/> + <xsd:attribute name="type" type="ST_EffectContainerType" use="optional" default="sib"/> + <xsd:attribute name="name" type="xsd:token" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_AlphaModulateEffect"> + <xsd:sequence> + <xsd:element name="cont" type="CT_EffectContainer" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BlendEffect"> + <xsd:sequence> + <xsd:element name="cont" type="CT_EffectContainer" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="blend" type="ST_BlendMode" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_EffectList"> + <xsd:sequence> + <xsd:element name="blur" type="CT_BlurEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fillOverlay" type="CT_FillOverlayEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="glow" type="CT_GlowEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="innerShdw" type="CT_InnerShadowEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="outerShdw" type="CT_OuterShadowEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="prstShdw" type="CT_PresetShadowEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="reflection" type="CT_ReflectionEffect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="softEdge" type="CT_SoftEdgesEffect" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_EffectProperties"> + <xsd:choice> + <xsd:element name="effectLst" type="CT_EffectList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="effectDag" type="CT_EffectContainer" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_EffectProperties"> + <xsd:sequence> + <xsd:group ref="EG_EffectProperties" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="blip" type="CT_Blip"/> + <xsd:simpleType name="ST_ShapeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="line"/> + <xsd:enumeration value="lineInv"/> + <xsd:enumeration value="triangle"/> + <xsd:enumeration value="rtTriangle"/> + <xsd:enumeration value="rect"/> + <xsd:enumeration value="diamond"/> + <xsd:enumeration value="parallelogram"/> + <xsd:enumeration value="trapezoid"/> + <xsd:enumeration value="nonIsoscelesTrapezoid"/> + <xsd:enumeration value="pentagon"/> + <xsd:enumeration value="hexagon"/> + <xsd:enumeration value="heptagon"/> + <xsd:enumeration value="octagon"/> + <xsd:enumeration value="decagon"/> + <xsd:enumeration value="dodecagon"/> + <xsd:enumeration value="star4"/> + <xsd:enumeration value="star5"/> + <xsd:enumeration value="star6"/> + <xsd:enumeration value="star7"/> + <xsd:enumeration value="star8"/> + <xsd:enumeration value="star10"/> + <xsd:enumeration value="star12"/> + <xsd:enumeration value="star16"/> + <xsd:enumeration value="star24"/> + <xsd:enumeration value="star32"/> + <xsd:enumeration value="roundRect"/> + <xsd:enumeration value="round1Rect"/> + <xsd:enumeration value="round2SameRect"/> + <xsd:enumeration value="round2DiagRect"/> + <xsd:enumeration value="snipRoundRect"/> + <xsd:enumeration value="snip1Rect"/> + <xsd:enumeration value="snip2SameRect"/> + <xsd:enumeration value="snip2DiagRect"/> + <xsd:enumeration value="plaque"/> + <xsd:enumeration value="ellipse"/> + <xsd:enumeration value="teardrop"/> + <xsd:enumeration value="homePlate"/> + <xsd:enumeration value="chevron"/> + <xsd:enumeration value="pieWedge"/> + <xsd:enumeration value="pie"/> + <xsd:enumeration value="blockArc"/> + <xsd:enumeration value="donut"/> + <xsd:enumeration value="noSmoking"/> + <xsd:enumeration value="rightArrow"/> + <xsd:enumeration value="leftArrow"/> + <xsd:enumeration value="upArrow"/> + <xsd:enumeration value="downArrow"/> + <xsd:enumeration value="stripedRightArrow"/> + <xsd:enumeration value="notchedRightArrow"/> + <xsd:enumeration value="bentUpArrow"/> + <xsd:enumeration value="leftRightArrow"/> + <xsd:enumeration value="upDownArrow"/> + <xsd:enumeration value="leftUpArrow"/> + <xsd:enumeration value="leftRightUpArrow"/> + <xsd:enumeration value="quadArrow"/> + <xsd:enumeration value="leftArrowCallout"/> + <xsd:enumeration value="rightArrowCallout"/> + <xsd:enumeration value="upArrowCallout"/> + <xsd:enumeration value="downArrowCallout"/> + <xsd:enumeration value="leftRightArrowCallout"/> + <xsd:enumeration value="upDownArrowCallout"/> + <xsd:enumeration value="quadArrowCallout"/> + <xsd:enumeration value="bentArrow"/> + <xsd:enumeration value="uturnArrow"/> + <xsd:enumeration value="circularArrow"/> + <xsd:enumeration value="leftCircularArrow"/> + <xsd:enumeration value="leftRightCircularArrow"/> + <xsd:enumeration value="curvedRightArrow"/> + <xsd:enumeration value="curvedLeftArrow"/> + <xsd:enumeration value="curvedUpArrow"/> + <xsd:enumeration value="curvedDownArrow"/> + <xsd:enumeration value="swooshArrow"/> + <xsd:enumeration value="cube"/> + <xsd:enumeration value="can"/> + <xsd:enumeration value="lightningBolt"/> + <xsd:enumeration value="heart"/> + <xsd:enumeration value="sun"/> + <xsd:enumeration value="moon"/> + <xsd:enumeration value="smileyFace"/> + <xsd:enumeration value="irregularSeal1"/> + <xsd:enumeration value="irregularSeal2"/> + <xsd:enumeration value="foldedCorner"/> + <xsd:enumeration value="bevel"/> + <xsd:enumeration value="frame"/> + <xsd:enumeration value="halfFrame"/> + <xsd:enumeration value="corner"/> + <xsd:enumeration value="diagStripe"/> + <xsd:enumeration value="chord"/> + <xsd:enumeration value="arc"/> + <xsd:enumeration value="leftBracket"/> + <xsd:enumeration value="rightBracket"/> + <xsd:enumeration value="leftBrace"/> + <xsd:enumeration value="rightBrace"/> + <xsd:enumeration value="bracketPair"/> + <xsd:enumeration value="bracePair"/> + <xsd:enumeration value="straightConnector1"/> + <xsd:enumeration value="bentConnector2"/> + <xsd:enumeration value="bentConnector3"/> + <xsd:enumeration value="bentConnector4"/> + <xsd:enumeration value="bentConnector5"/> + <xsd:enumeration value="curvedConnector2"/> + <xsd:enumeration value="curvedConnector3"/> + <xsd:enumeration value="curvedConnector4"/> + <xsd:enumeration value="curvedConnector5"/> + <xsd:enumeration value="callout1"/> + <xsd:enumeration value="callout2"/> + <xsd:enumeration value="callout3"/> + <xsd:enumeration value="accentCallout1"/> + <xsd:enumeration value="accentCallout2"/> + <xsd:enumeration value="accentCallout3"/> + <xsd:enumeration value="borderCallout1"/> + <xsd:enumeration value="borderCallout2"/> + <xsd:enumeration value="borderCallout3"/> + <xsd:enumeration value="accentBorderCallout1"/> + <xsd:enumeration value="accentBorderCallout2"/> + <xsd:enumeration value="accentBorderCallout3"/> + <xsd:enumeration value="wedgeRectCallout"/> + <xsd:enumeration value="wedgeRoundRectCallout"/> + <xsd:enumeration value="wedgeEllipseCallout"/> + <xsd:enumeration value="cloudCallout"/> + <xsd:enumeration value="cloud"/> + <xsd:enumeration value="ribbon"/> + <xsd:enumeration value="ribbon2"/> + <xsd:enumeration value="ellipseRibbon"/> + <xsd:enumeration value="ellipseRibbon2"/> + <xsd:enumeration value="leftRightRibbon"/> + <xsd:enumeration value="verticalScroll"/> + <xsd:enumeration value="horizontalScroll"/> + <xsd:enumeration value="wave"/> + <xsd:enumeration value="doubleWave"/> + <xsd:enumeration value="plus"/> + <xsd:enumeration value="flowChartProcess"/> + <xsd:enumeration value="flowChartDecision"/> + <xsd:enumeration value="flowChartInputOutput"/> + <xsd:enumeration value="flowChartPredefinedProcess"/> + <xsd:enumeration value="flowChartInternalStorage"/> + <xsd:enumeration value="flowChartDocument"/> + <xsd:enumeration value="flowChartMultidocument"/> + <xsd:enumeration value="flowChartTerminator"/> + <xsd:enumeration value="flowChartPreparation"/> + <xsd:enumeration value="flowChartManualInput"/> + <xsd:enumeration value="flowChartManualOperation"/> + <xsd:enumeration value="flowChartConnector"/> + <xsd:enumeration value="flowChartPunchedCard"/> + <xsd:enumeration value="flowChartPunchedTape"/> + <xsd:enumeration value="flowChartSummingJunction"/> + <xsd:enumeration value="flowChartOr"/> + <xsd:enumeration value="flowChartCollate"/> + <xsd:enumeration value="flowChartSort"/> + <xsd:enumeration value="flowChartExtract"/> + <xsd:enumeration value="flowChartMerge"/> + <xsd:enumeration value="flowChartOfflineStorage"/> + <xsd:enumeration value="flowChartOnlineStorage"/> + <xsd:enumeration value="flowChartMagneticTape"/> + <xsd:enumeration value="flowChartMagneticDisk"/> + <xsd:enumeration value="flowChartMagneticDrum"/> + <xsd:enumeration value="flowChartDisplay"/> + <xsd:enumeration value="flowChartDelay"/> + <xsd:enumeration value="flowChartAlternateProcess"/> + <xsd:enumeration value="flowChartOffpageConnector"/> + <xsd:enumeration value="actionButtonBlank"/> + <xsd:enumeration value="actionButtonHome"/> + <xsd:enumeration value="actionButtonHelp"/> + <xsd:enumeration value="actionButtonInformation"/> + <xsd:enumeration value="actionButtonForwardNext"/> + <xsd:enumeration value="actionButtonBackPrevious"/> + <xsd:enumeration value="actionButtonEnd"/> + <xsd:enumeration value="actionButtonBeginning"/> + <xsd:enumeration value="actionButtonReturn"/> + <xsd:enumeration value="actionButtonDocument"/> + <xsd:enumeration value="actionButtonSound"/> + <xsd:enumeration value="actionButtonMovie"/> + <xsd:enumeration value="gear6"/> + <xsd:enumeration value="gear9"/> + <xsd:enumeration value="funnel"/> + <xsd:enumeration value="mathPlus"/> + <xsd:enumeration value="mathMinus"/> + <xsd:enumeration value="mathMultiply"/> + <xsd:enumeration value="mathDivide"/> + <xsd:enumeration value="mathEqual"/> + <xsd:enumeration value="mathNotEqual"/> + <xsd:enumeration value="cornerTabs"/> + <xsd:enumeration value="squareTabs"/> + <xsd:enumeration value="plaqueTabs"/> + <xsd:enumeration value="chartX"/> + <xsd:enumeration value="chartStar"/> + <xsd:enumeration value="chartPlus"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextShapeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="textNoShape"/> + <xsd:enumeration value="textPlain"/> + <xsd:enumeration value="textStop"/> + <xsd:enumeration value="textTriangle"/> + <xsd:enumeration value="textTriangleInverted"/> + <xsd:enumeration value="textChevron"/> + <xsd:enumeration value="textChevronInverted"/> + <xsd:enumeration value="textRingInside"/> + <xsd:enumeration value="textRingOutside"/> + <xsd:enumeration value="textArchUp"/> + <xsd:enumeration value="textArchDown"/> + <xsd:enumeration value="textCircle"/> + <xsd:enumeration value="textButton"/> + <xsd:enumeration value="textArchUpPour"/> + <xsd:enumeration value="textArchDownPour"/> + <xsd:enumeration value="textCirclePour"/> + <xsd:enumeration value="textButtonPour"/> + <xsd:enumeration value="textCurveUp"/> + <xsd:enumeration value="textCurveDown"/> + <xsd:enumeration value="textCanUp"/> + <xsd:enumeration value="textCanDown"/> + <xsd:enumeration value="textWave1"/> + <xsd:enumeration value="textWave2"/> + <xsd:enumeration value="textDoubleWave1"/> + <xsd:enumeration value="textWave4"/> + <xsd:enumeration value="textInflate"/> + <xsd:enumeration value="textDeflate"/> + <xsd:enumeration value="textInflateBottom"/> + <xsd:enumeration value="textDeflateBottom"/> + <xsd:enumeration value="textInflateTop"/> + <xsd:enumeration value="textDeflateTop"/> + <xsd:enumeration value="textDeflateInflate"/> + <xsd:enumeration value="textDeflateInflateDeflate"/> + <xsd:enumeration value="textFadeRight"/> + <xsd:enumeration value="textFadeLeft"/> + <xsd:enumeration value="textFadeUp"/> + <xsd:enumeration value="textFadeDown"/> + <xsd:enumeration value="textSlantUp"/> + <xsd:enumeration value="textSlantDown"/> + <xsd:enumeration value="textCascadeUp"/> + <xsd:enumeration value="textCascadeDown"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_GeomGuideName"> + <xsd:restriction base="xsd:token"/> + </xsd:simpleType> + <xsd:simpleType name="ST_GeomGuideFormula"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:complexType name="CT_GeomGuide"> + <xsd:attribute name="name" type="ST_GeomGuideName" use="required"/> + <xsd:attribute name="fmla" type="ST_GeomGuideFormula" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_GeomGuideList"> + <xsd:sequence> + <xsd:element name="gd" type="CT_GeomGuide" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_AdjCoordinate"> + <xsd:union memberTypes="ST_Coordinate ST_GeomGuideName"/> + </xsd:simpleType> + <xsd:simpleType name="ST_AdjAngle"> + <xsd:union memberTypes="ST_Angle ST_GeomGuideName"/> + </xsd:simpleType> + <xsd:complexType name="CT_AdjPoint2D"> + <xsd:attribute name="x" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="y" type="ST_AdjCoordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_GeomRect"> + <xsd:attribute name="l" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="t" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="r" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="b" type="ST_AdjCoordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_XYAdjustHandle"> + <xsd:sequence> + <xsd:element name="pos" type="CT_AdjPoint2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="gdRefX" type="ST_GeomGuideName" use="optional"/> + <xsd:attribute name="minX" type="ST_AdjCoordinate" use="optional"/> + <xsd:attribute name="maxX" type="ST_AdjCoordinate" use="optional"/> + <xsd:attribute name="gdRefY" type="ST_GeomGuideName" use="optional"/> + <xsd:attribute name="minY" type="ST_AdjCoordinate" use="optional"/> + <xsd:attribute name="maxY" type="ST_AdjCoordinate" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PolarAdjustHandle"> + <xsd:sequence> + <xsd:element name="pos" type="CT_AdjPoint2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="gdRefR" type="ST_GeomGuideName" use="optional"/> + <xsd:attribute name="minR" type="ST_AdjCoordinate" use="optional"/> + <xsd:attribute name="maxR" type="ST_AdjCoordinate" use="optional"/> + <xsd:attribute name="gdRefAng" type="ST_GeomGuideName" use="optional"/> + <xsd:attribute name="minAng" type="ST_AdjAngle" use="optional"/> + <xsd:attribute name="maxAng" type="ST_AdjAngle" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ConnectionSite"> + <xsd:sequence> + <xsd:element name="pos" type="CT_AdjPoint2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ang" type="ST_AdjAngle" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AdjustHandleList"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="ahXY" type="CT_XYAdjustHandle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="ahPolar" type="CT_PolarAdjustHandle" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_ConnectionSiteList"> + <xsd:sequence> + <xsd:element name="cxn" type="CT_ConnectionSite" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Connection"> + <xsd:attribute name="id" type="ST_DrawingElementId" use="required"/> + <xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Path2DMoveTo"> + <xsd:sequence> + <xsd:element name="pt" type="CT_AdjPoint2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Path2DLineTo"> + <xsd:sequence> + <xsd:element name="pt" type="CT_AdjPoint2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Path2DArcTo"> + <xsd:attribute name="wR" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="hR" type="ST_AdjCoordinate" use="required"/> + <xsd:attribute name="stAng" type="ST_AdjAngle" use="required"/> + <xsd:attribute name="swAng" type="ST_AdjAngle" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Path2DQuadBezierTo"> + <xsd:sequence> + <xsd:element name="pt" type="CT_AdjPoint2D" minOccurs="2" maxOccurs="2"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Path2DCubicBezierTo"> + <xsd:sequence> + <xsd:element name="pt" type="CT_AdjPoint2D" minOccurs="3" maxOccurs="3"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Path2DClose"/> + <xsd:simpleType name="ST_PathFillMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="norm"/> + <xsd:enumeration value="lighten"/> + <xsd:enumeration value="lightenLess"/> + <xsd:enumeration value="darken"/> + <xsd:enumeration value="darkenLess"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Path2D"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="close" type="CT_Path2DClose" minOccurs="1" maxOccurs="1"/> + <xsd:element name="moveTo" type="CT_Path2DMoveTo" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lnTo" type="CT_Path2DLineTo" minOccurs="1" maxOccurs="1"/> + <xsd:element name="arcTo" type="CT_Path2DArcTo" minOccurs="1" maxOccurs="1"/> + <xsd:element name="quadBezTo" type="CT_Path2DQuadBezierTo" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cubicBezTo" type="CT_Path2DCubicBezierTo" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="w" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="h" type="ST_PositiveCoordinate" use="optional" default="0"/> + <xsd:attribute name="fill" type="ST_PathFillMode" use="optional" default="norm"/> + <xsd:attribute name="stroke" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="extrusionOk" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_Path2DList"> + <xsd:sequence> + <xsd:element name="path" type="CT_Path2D" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PresetGeometry2D"> + <xsd:sequence> + <xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prst" type="ST_ShapeType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PresetTextShape"> + <xsd:sequence> + <xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prst" type="ST_TextShapeType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomGeometry2D"> + <xsd:sequence> + <xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="gdLst" type="CT_GeomGuideList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ahLst" type="CT_AdjustHandleList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cxnLst" type="CT_ConnectionSiteList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rect" type="CT_GeomRect" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pathLst" type="CT_Path2DList" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_Geometry"> + <xsd:choice> + <xsd:element name="custGeom" type="CT_CustomGeometry2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="prstGeom" type="CT_PresetGeometry2D" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_TextGeometry"> + <xsd:choice> + <xsd:element name="custGeom" type="CT_CustomGeometry2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_LineEndType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="triangle"/> + <xsd:enumeration value="stealth"/> + <xsd:enumeration value="diamond"/> + <xsd:enumeration value="oval"/> + <xsd:enumeration value="arrow"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LineEndWidth"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sm"/> + <xsd:enumeration value="med"/> + <xsd:enumeration value="lg"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LineEndLength"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sm"/> + <xsd:enumeration value="med"/> + <xsd:enumeration value="lg"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LineEndProperties"> + <xsd:attribute name="type" type="ST_LineEndType" use="optional" default="none"/> + <xsd:attribute name="w" type="ST_LineEndWidth" use="optional"/> + <xsd:attribute name="len" type="ST_LineEndLength" use="optional"/> + </xsd:complexType> + <xsd:group name="EG_LineFillProperties"> + <xsd:choice> + <xsd:element name="noFill" type="CT_NoFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="solidFill" type="CT_SolidColorFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gradFill" type="CT_GradientFillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="pattFill" type="CT_PatternFillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_LineJoinBevel"/> + <xsd:complexType name="CT_LineJoinRound"/> + <xsd:complexType name="CT_LineJoinMiterProperties"> + <xsd:attribute name="lim" type="ST_PositivePercentage" use="optional"/> + </xsd:complexType> + <xsd:group name="EG_LineJoinProperties"> + <xsd:choice> + <xsd:element name="round" type="CT_LineJoinRound" minOccurs="1" maxOccurs="1"/> + <xsd:element name="bevel" type="CT_LineJoinBevel" minOccurs="1" maxOccurs="1"/> + <xsd:element name="miter" type="CT_LineJoinMiterProperties" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_PresetLineDashVal"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="solid"/> + <xsd:enumeration value="dot"/> + <xsd:enumeration value="dash"/> + <xsd:enumeration value="lgDash"/> + <xsd:enumeration value="dashDot"/> + <xsd:enumeration value="lgDashDot"/> + <xsd:enumeration value="lgDashDotDot"/> + <xsd:enumeration value="sysDash"/> + <xsd:enumeration value="sysDot"/> + <xsd:enumeration value="sysDashDot"/> + <xsd:enumeration value="sysDashDotDot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PresetLineDashProperties"> + <xsd:attribute name="val" type="ST_PresetLineDashVal" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DashStop"> + <xsd:attribute name="d" type="ST_PositivePercentage" use="required"/> + <xsd:attribute name="sp" type="ST_PositivePercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DashStopList"> + <xsd:sequence> + <xsd:element name="ds" type="CT_DashStop" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_LineDashProperties"> + <xsd:choice> + <xsd:element name="prstDash" type="CT_PresetLineDashProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="custDash" type="CT_DashStopList" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_LineCap"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="rnd"/> + <xsd:enumeration value="sq"/> + <xsd:enumeration value="flat"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LineWidth"> + <xsd:restriction base="ST_Coordinate32Unqualified"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="20116800"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PenAlignment"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="in"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CompoundLine"> + <xsd:restriction base="xsd:token"> + <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_LineProperties"> + <xsd:sequence> + <xsd:group ref="EG_LineFillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_LineDashProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_LineJoinProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headEnd" type="CT_LineEndProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tailEnd" type="CT_LineEndProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="w" type="ST_LineWidth" use="optional"/> + <xsd:attribute name="cap" type="ST_LineCap" use="optional"/> + <xsd:attribute name="cmpd" type="ST_CompoundLine" use="optional"/> + <xsd:attribute name="algn" type="ST_PenAlignment" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_ShapeID"> + <xsd:restriction base="xsd:token"/> + </xsd:simpleType> + <xsd:complexType name="CT_ShapeProperties"> + <xsd:sequence> + <xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_Geometry" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ln" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupShapeProperties"> + <xsd:sequence> + <xsd:element name="xfrm" type="CT_GroupTransform2D" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_StyleMatrixReference"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="idx" type="ST_StyleMatrixColumnIndex" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FontReference"> + <xsd:sequence> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="idx" type="ST_FontCollectionIndex" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ShapeStyle"> + <xsd:sequence> + <xsd:element name="lnRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fillRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + <xsd:element name="effectRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fontRef" type="CT_FontReference" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DefaultShapeDefinition"> + <xsd:sequence> + <xsd:element name="spPr" type="CT_ShapeProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="1" maxOccurs="1"/> + <xsd:element name="style" type="CT_ShapeStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ObjectStyleDefaults"> + <xsd:sequence> + <xsd:element name="spDef" type="CT_DefaultShapeDefinition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnDef" type="CT_DefaultShapeDefinition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txDef" type="CT_DefaultShapeDefinition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EmptyElement"/> + <xsd:complexType name="CT_ColorMapping"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="bg1" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="tx1" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="bg2" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="tx2" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent1" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent2" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent3" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent4" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent5" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="accent6" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="hlink" type="ST_ColorSchemeIndex" use="required"/> + <xsd:attribute name="folHlink" type="ST_ColorSchemeIndex" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ColorMappingOverride"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="masterClrMapping" type="CT_EmptyElement"/> + <xsd:element name="overrideClrMapping" type="CT_ColorMapping"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ColorSchemeAndMapping"> + <xsd:sequence> + <xsd:element name="clrScheme" type="CT_ColorScheme" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrMap" type="CT_ColorMapping" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ColorSchemeList"> + <xsd:sequence> + <xsd:element name="extraClrScheme" type="CT_ColorSchemeAndMapping" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OfficeStyleSheet"> + <xsd:sequence> + <xsd:element name="themeElements" type="CT_BaseStyles" minOccurs="1" maxOccurs="1"/> + <xsd:element name="objectDefaults" type="CT_ObjectStyleDefaults" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extraClrSchemeLst" type="CT_ColorSchemeList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="custClrLst" type="CT_CustomColorList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_BaseStylesOverride"> + <xsd:sequence> + <xsd:element name="clrScheme" type="CT_ColorScheme" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fontScheme" type="CT_FontScheme" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fmtScheme" type="CT_StyleMatrix" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ClipboardStyleSheet"> + <xsd:sequence> + <xsd:element name="themeElements" type="CT_BaseStyles" minOccurs="1" maxOccurs="1"/> + <xsd:element name="clrMap" type="CT_ColorMapping" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="theme" type="CT_OfficeStyleSheet"/> + <xsd:element name="themeOverride" type="CT_BaseStylesOverride"/> + <xsd:element name="themeManager" type="CT_EmptyElement"/> + <xsd:complexType name="CT_TableCellProperties"> + <xsd:sequence> + <xsd:element name="lnL" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnR" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnT" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnB" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnTlToBr" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lnBlToTr" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cell3D" type="CT_Cell3D" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headers" type="CT_Headers" minOccurs="0"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="marL" type="ST_Coordinate32" use="optional" default="91440"/> + <xsd:attribute name="marR" type="ST_Coordinate32" use="optional" default="91440"/> + <xsd:attribute name="marT" type="ST_Coordinate32" use="optional" default="45720"/> + <xsd:attribute name="marB" type="ST_Coordinate32" use="optional" default="45720"/> + <xsd:attribute name="vert" type="ST_TextVerticalType" use="optional" default="horz"/> + <xsd:attribute name="anchor" type="ST_TextAnchoringType" use="optional" default="t"/> + <xsd:attribute name="anchorCtr" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType" use="optional" default="clip" + /> + </xsd:complexType> + <xsd:complexType name="CT_Headers"> + <xsd:sequence minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="header" type="xsd:string"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TableCol"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="w" type="ST_Coordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TableGrid"> + <xsd:sequence> + <xsd:element name="gridCol" type="CT_TableCol" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TableCell"> + <xsd:sequence> + <xsd:element name="txBody" type="CT_TextBody" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcPr" type="CT_TableCellProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rowSpan" type="xsd:int" use="optional" default="1"/> + <xsd:attribute name="gridSpan" type="xsd:int" use="optional" default="1"/> + <xsd:attribute name="hMerge" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="vMerge" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="id" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableRow"> + <xsd:sequence> + <xsd:element name="tc" type="CT_TableCell" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="h" type="ST_Coordinate" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TableProperties"> + <xsd:sequence> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="tableStyle" type="CT_TableStyle"/> + <xsd:element name="tableStyleId" type="s:ST_Guid"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rtl" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="firstRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="firstCol" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="lastRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="lastCol" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="bandRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="bandCol" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Table"> + <xsd:sequence> + <xsd:element name="tblPr" type="CT_TableProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblGrid" type="CT_TableGrid" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tr" type="CT_TableRow" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="tbl" type="CT_Table"/> + <xsd:complexType name="CT_Cell3D"> + <xsd:sequence> + <xsd:element name="bevel" type="CT_Bevel" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lightRig" type="CT_LightRig" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prstMaterial" type="ST_PresetMaterialType" use="optional" default="plastic" + /> + </xsd:complexType> + <xsd:group name="EG_ThemeableFillStyle"> + <xsd:choice> + <xsd:element name="fill" type="CT_FillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fillRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_ThemeableLineStyle"> + <xsd:choice> + <xsd:element name="ln" type="CT_LineProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lnRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:complexType> + <xsd:group name="EG_ThemeableEffectStyle"> + <xsd:choice> + <xsd:element name="effect" type="CT_EffectProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="effectRef" type="CT_StyleMatrixReference" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_ThemeableFontStyles"> + <xsd:choice> + <xsd:element name="font" type="CT_FontCollection" minOccurs="1" maxOccurs="1"/> + <xsd:element name="fontRef" type="CT_FontReference" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_OnOffStyleType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="on"/> + <xsd:enumeration value="off"/> + <xsd:enumeration value="def"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TableStyleTextStyle"> + <xsd:sequence> + <xsd:group ref="EG_ThemeableFontStyles" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="b" type="ST_OnOffStyleType" use="optional" default="def"/> + <xsd:attribute name="i" type="ST_OnOffStyleType" use="optional" default="def"/> + </xsd:complexType> + <xsd:complexType name="CT_TableCellBorderStyle"> + <xsd:sequence> + <xsd:element name="left" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="right" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="top" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bottom" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="insideH" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="insideV" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tl2br" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tr2bl" type="CT_ThemeableLineStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TableBackgroundStyle"> + <xsd:sequence> + <xsd:group ref="EG_ThemeableFillStyle" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ThemeableEffectStyle" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TableStyleCellStyle"> + <xsd:sequence> + <xsd:element name="tcBdr" type="CT_TableCellBorderStyle" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ThemeableFillStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cell3D" type="CT_Cell3D" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TablePartStyle"> + <xsd:sequence> + <xsd:element name="tcTxStyle" type="CT_TableStyleTextStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcStyle" type="CT_TableStyleCellStyle" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TableStyle"> + <xsd:sequence> + <xsd:element name="tblBg" type="CT_TableBackgroundStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="wholeTbl" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="band1H" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="band2H" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="band1V" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="band2V" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lastCol" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstCol" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lastRow" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="seCell" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="swCell" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstRow" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="neCell" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="nwCell" type="CT_TablePartStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="styleId" type="s:ST_Guid" use="required"/> + <xsd:attribute name="styleName" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TableStyleList"> + <xsd:sequence> + <xsd:element name="tblStyle" type="CT_TableStyle" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="def" type="s:ST_Guid" use="required"/> + </xsd:complexType> + <xsd:element name="tblStyleLst" type="CT_TableStyleList"/> + <xsd:complexType name="CT_TextParagraph"> + <xsd:sequence> + <xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextRun" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="endParaRPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TextAnchoringType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="t"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="just"/> + <xsd:enumeration value="dist"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextVertOverflowType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="overflow"/> + <xsd:enumeration value="ellipsis"/> + <xsd:enumeration value="clip"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextHorzOverflowType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="overflow"/> + <xsd:enumeration value="clip"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextVerticalType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="horz"/> + <xsd:enumeration value="vert"/> + <xsd:enumeration value="vert270"/> + <xsd:enumeration value="wordArtVert"/> + <xsd:enumeration value="eaVert"/> + <xsd:enumeration value="mongolianVert"/> + <xsd:enumeration value="wordArtVertRtl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextWrappingType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="square"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextColumnCount"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="1"/> + <xsd:maxInclusive value="16"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextListStyle"> + <xsd:sequence> + <xsd:element name="defPPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl1pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl2pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl3pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl4pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl5pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl6pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl7pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl8pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="lvl9pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TextFontScalePercentOrPercentString"> + <xsd:union memberTypes="ST_TextFontScalePercent s:ST_Percentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TextFontScalePercent"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="1000"/> + <xsd:maxInclusive value="100000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextNormalAutofit"> + <xsd:attribute name="fontScale" type="ST_TextFontScalePercentOrPercentString" use="optional" + default="100%"/> + <xsd:attribute name="lnSpcReduction" type="ST_TextSpacingPercentOrPercentString" use="optional" + default="0%"/> + </xsd:complexType> + <xsd:complexType name="CT_TextShapeAutofit"/> + <xsd:complexType name="CT_TextNoAutofit"/> + <xsd:group name="EG_TextAutofit"> + <xsd:choice> + <xsd:element name="noAutofit" type="CT_TextNoAutofit"/> + <xsd:element name="normAutofit" type="CT_TextNormalAutofit"/> + <xsd:element name="spAutoFit" type="CT_TextShapeAutofit"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_TextBodyProperties"> + <xsd:sequence> + <xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextAutofit" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_Text3D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="rot" type="ST_Angle" use="optional"/> + <xsd:attribute name="spcFirstLastPara" type="xsd:boolean" use="optional"/> + <xsd:attribute name="vertOverflow" type="ST_TextVertOverflowType" use="optional"/> + <xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType" use="optional"/> + <xsd:attribute name="vert" type="ST_TextVerticalType" use="optional"/> + <xsd:attribute name="wrap" type="ST_TextWrappingType" use="optional"/> + <xsd:attribute name="lIns" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="tIns" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="rIns" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="bIns" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="numCol" type="ST_TextColumnCount" use="optional"/> + <xsd:attribute name="spcCol" type="ST_PositiveCoordinate32" use="optional"/> + <xsd:attribute name="rtlCol" type="xsd:boolean" use="optional"/> + <xsd:attribute name="fromWordArt" type="xsd:boolean" use="optional"/> + <xsd:attribute name="anchor" type="ST_TextAnchoringType" use="optional"/> + <xsd:attribute name="anchorCtr" type="xsd:boolean" use="optional"/> + <xsd:attribute name="forceAA" type="xsd:boolean" use="optional"/> + <xsd:attribute name="upright" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="compatLnSpc" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TextBody"> + <xsd:sequence> + <xsd:element name="bodyPr" type="CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="p" type="CT_TextParagraph" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TextBulletStartAtNum"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="1"/> + <xsd:maxInclusive value="32767"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextAutonumberScheme"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="alphaLcParenBoth"/> + <xsd:enumeration value="alphaUcParenBoth"/> + <xsd:enumeration value="alphaLcParenR"/> + <xsd:enumeration value="alphaUcParenR"/> + <xsd:enumeration value="alphaLcPeriod"/> + <xsd:enumeration value="alphaUcPeriod"/> + <xsd:enumeration value="arabicParenBoth"/> + <xsd:enumeration value="arabicParenR"/> + <xsd:enumeration value="arabicPeriod"/> + <xsd:enumeration value="arabicPlain"/> + <xsd:enumeration value="romanLcParenBoth"/> + <xsd:enumeration value="romanUcParenBoth"/> + <xsd:enumeration value="romanLcParenR"/> + <xsd:enumeration value="romanUcParenR"/> + <xsd:enumeration value="romanLcPeriod"/> + <xsd:enumeration value="romanUcPeriod"/> + <xsd:enumeration value="circleNumDbPlain"/> + <xsd:enumeration value="circleNumWdBlackPlain"/> + <xsd:enumeration value="circleNumWdWhitePlain"/> + <xsd:enumeration value="arabicDbPeriod"/> + <xsd:enumeration value="arabicDbPlain"/> + <xsd:enumeration value="ea1ChsPeriod"/> + <xsd:enumeration value="ea1ChsPlain"/> + <xsd:enumeration value="ea1ChtPeriod"/> + <xsd:enumeration value="ea1ChtPlain"/> + <xsd:enumeration value="ea1JpnChsDbPeriod"/> + <xsd:enumeration value="ea1JpnKorPlain"/> + <xsd:enumeration value="ea1JpnKorPeriod"/> + <xsd:enumeration value="arabic1Minus"/> + <xsd:enumeration value="arabic2Minus"/> + <xsd:enumeration value="hebrew2Minus"/> + <xsd:enumeration value="thaiAlphaPeriod"/> + <xsd:enumeration value="thaiAlphaParenR"/> + <xsd:enumeration value="thaiAlphaParenBoth"/> + <xsd:enumeration value="thaiNumPeriod"/> + <xsd:enumeration value="thaiNumParenR"/> + <xsd:enumeration value="thaiNumParenBoth"/> + <xsd:enumeration value="hindiAlphaPeriod"/> + <xsd:enumeration value="hindiNumPeriod"/> + <xsd:enumeration value="hindiNumParenR"/> + <xsd:enumeration value="hindiAlpha1Period"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextBulletColorFollowText"/> + <xsd:group name="EG_TextBulletColor"> + <xsd:choice> + <xsd:element name="buClrTx" type="CT_TextBulletColorFollowText" minOccurs="1" maxOccurs="1"/> + <xsd:element name="buClr" type="CT_Color" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_TextBulletSize"> + <xsd:union memberTypes="ST_TextBulletSizePercent ST_TextBulletSizeDecimal"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TextBulletSizePercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*((2[5-9])|([3-9][0-9])|([1-3][0-9][0-9])|400)%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextBulletSizeDecimal"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="25000"/> + <xsd:maxInclusive value="400000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextBulletSizeFollowText"/> + <xsd:complexType name="CT_TextBulletSizePercent"> + <xsd:attribute name="val" type="ST_TextBulletSizePercent" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TextBulletSizePoint"> + <xsd:attribute name="val" type="ST_TextFontSize" use="required"/> + </xsd:complexType> + <xsd:group name="EG_TextBulletSize"> + <xsd:choice> + <xsd:element name="buSzTx" type="CT_TextBulletSizeFollowText"/> + <xsd:element name="buSzPct" type="CT_TextBulletSizePercent"/> + <xsd:element name="buSzPts" type="CT_TextBulletSizePoint"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_TextBulletTypefaceFollowText"/> + <xsd:group name="EG_TextBulletTypeface"> + <xsd:choice> + <xsd:element name="buFontTx" type="CT_TextBulletTypefaceFollowText"/> + <xsd:element name="buFont" type="CT_TextFont"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_TextAutonumberBullet"> + <xsd:attribute name="type" type="ST_TextAutonumberScheme" use="required"/> + <xsd:attribute name="startAt" type="ST_TextBulletStartAtNum" use="optional" default="1"/> + </xsd:complexType> + <xsd:complexType name="CT_TextCharBullet"> + <xsd:attribute name="char" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TextBlipBullet"> + <xsd:sequence> + <xsd:element name="blip" type="CT_Blip" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TextNoBullet"/> + <xsd:group name="EG_TextBullet"> + <xsd:choice> + <xsd:element name="buNone" type="CT_TextNoBullet"/> + <xsd:element name="buAutoNum" type="CT_TextAutonumberBullet"/> + <xsd:element name="buChar" type="CT_TextCharBullet"/> + <xsd:element name="buBlip" type="CT_TextBlipBullet"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_TextPoint"> + <xsd:union memberTypes="ST_TextPointUnqualified s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TextPointUnqualified"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="-400000"/> + <xsd:maxInclusive value="400000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextNonNegativePoint"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="400000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextFontSize"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="100"/> + <xsd:maxInclusive value="400000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextTypeface"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PitchFamily"> + <xsd:restriction base="xsd:byte"> + <xsd:enumeration value="00"/> + <xsd:enumeration value="01"/> + <xsd:enumeration value="02"/> + <xsd:enumeration value="16"/> + <xsd:enumeration value="17"/> + <xsd:enumeration value="18"/> + <xsd:enumeration value="32"/> + <xsd:enumeration value="33"/> + <xsd:enumeration value="34"/> + <xsd:enumeration value="48"/> + <xsd:enumeration value="49"/> + <xsd:enumeration value="50"/> + <xsd:enumeration value="64"/> + <xsd:enumeration value="65"/> + <xsd:enumeration value="66"/> + <xsd:enumeration value="80"/> + <xsd:enumeration value="81"/> + <xsd:enumeration value="82"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextFont"> + <xsd:attribute name="typeface" type="ST_TextTypeface" use="required"/> + <xsd:attribute name="panose" type="s:ST_Panose" use="optional"/> + <xsd:attribute name="pitchFamily" type="ST_PitchFamily" use="optional" default="0"/> + <xsd:attribute name="charset" type="xsd:byte" use="optional" default="1"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextUnderlineType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="words"/> + <xsd:enumeration value="sng"/> + <xsd:enumeration value="dbl"/> + <xsd:enumeration value="heavy"/> + <xsd:enumeration value="dotted"/> + <xsd:enumeration value="dottedHeavy"/> + <xsd:enumeration value="dash"/> + <xsd:enumeration value="dashHeavy"/> + <xsd:enumeration value="dashLong"/> + <xsd:enumeration value="dashLongHeavy"/> + <xsd:enumeration value="dotDash"/> + <xsd:enumeration value="dotDashHeavy"/> + <xsd:enumeration value="dotDotDash"/> + <xsd:enumeration value="dotDotDashHeavy"/> + <xsd:enumeration value="wavy"/> + <xsd:enumeration value="wavyHeavy"/> + <xsd:enumeration value="wavyDbl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextUnderlineLineFollowText"/> + <xsd:complexType name="CT_TextUnderlineFillFollowText"/> + <xsd:complexType name="CT_TextUnderlineFillGroupWrapper"> + <xsd:group ref="EG_FillProperties" minOccurs="1" maxOccurs="1"/> + </xsd:complexType> + <xsd:group name="EG_TextUnderlineLine"> + <xsd:choice> + <xsd:element name="uLnTx" type="CT_TextUnderlineLineFollowText"/> + <xsd:element name="uLn" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_TextUnderlineFill"> + <xsd:choice> + <xsd:element name="uFillTx" type="CT_TextUnderlineFillFollowText"/> + <xsd:element name="uFill" type="CT_TextUnderlineFillGroupWrapper"/> + </xsd:choice> + </xsd:group> + <xsd:simpleType name="ST_TextStrikeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="noStrike"/> + <xsd:enumeration value="sngStrike"/> + <xsd:enumeration value="dblStrike"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextCapsType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="small"/> + <xsd:enumeration value="all"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextCharacterProperties"> + <xsd:sequence> + <xsd:element name="ln" type="CT_LineProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_FillProperties" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="highlight" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextUnderlineLine" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextUnderlineFill" minOccurs="0" maxOccurs="1"/> + <xsd:element name="latin" type="CT_TextFont" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ea" type="CT_TextFont" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cs" type="CT_TextFont" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sym" type="CT_TextFont" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hlinkMouseOver" type="CT_Hyperlink" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rtl" type="CT_Boolean" minOccurs="0"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="kumimoji" type="xsd:boolean" use="optional"/> + <xsd:attribute name="lang" type="s:ST_Lang" use="optional"/> + <xsd:attribute name="altLang" type="s:ST_Lang" use="optional"/> + <xsd:attribute name="sz" type="ST_TextFontSize" use="optional"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional"/> + <xsd:attribute name="u" type="ST_TextUnderlineType" use="optional"/> + <xsd:attribute name="strike" type="ST_TextStrikeType" use="optional"/> + <xsd:attribute name="kern" type="ST_TextNonNegativePoint" use="optional"/> + <xsd:attribute name="cap" type="ST_TextCapsType" use="optional" default="none"/> + <xsd:attribute name="spc" type="ST_TextPoint" use="optional"/> + <xsd:attribute name="normalizeH" type="xsd:boolean" use="optional"/> + <xsd:attribute name="baseline" type="ST_Percentage" use="optional"/> + <xsd:attribute name="noProof" type="xsd:boolean" use="optional"/> + <xsd:attribute name="dirty" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="err" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="smtClean" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="smtId" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="bmk" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Boolean"> + <xsd:attribute name="val" type="s:ST_OnOff" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextSpacingPoint"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="158400"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextSpacingPercentOrPercentString"> + <xsd:union memberTypes="ST_TextSpacingPercent s:ST_Percentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TextSpacingPercent"> + <xsd:restriction base="ST_PercentageDecimal"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="13200000"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextSpacingPercent"> + <xsd:attribute name="val" type="ST_TextSpacingPercentOrPercentString" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TextSpacingPoint"> + <xsd:attribute name="val" type="ST_TextSpacingPoint" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextMargin"> + <xsd:restriction base="ST_Coordinate32Unqualified"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="51206400"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextIndent"> + <xsd:restriction base="ST_Coordinate32Unqualified"> + <xsd:minInclusive value="-51206400"/> + <xsd:maxInclusive value="51206400"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextTabAlignType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="dec"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextTabStop"> + <xsd:attribute name="pos" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="algn" type="ST_TextTabAlignType" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TextTabStopList"> + <xsd:sequence> + <xsd:element name="tab" type="CT_TextTabStop" minOccurs="0" maxOccurs="32"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TextLineBreak"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TextSpacing"> + <xsd:choice> + <xsd:element name="spcPct" type="CT_TextSpacingPercent"/> + <xsd:element name="spcPts" type="CT_TextSpacingPoint"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TextAlignType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="just"/> + <xsd:enumeration value="justLow"/> + <xsd:enumeration value="dist"/> + <xsd:enumeration value="thaiDist"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextFontAlignType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="t"/> + <xsd:enumeration value="ctr"/> + <xsd:enumeration value="base"/> + <xsd:enumeration value="b"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextIndentLevelType"> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="8"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextParagraphProperties"> + <xsd:sequence> + <xsd:element name="lnSpc" type="CT_TextSpacing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spcBef" type="CT_TextSpacing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spcAft" type="CT_TextSpacing" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextBulletColor" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextBulletSize" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextBulletTypeface" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_TextBullet" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tabLst" type="CT_TextTabStopList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="defRPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="marL" type="ST_TextMargin" use="optional"/> + <xsd:attribute name="marR" type="ST_TextMargin" use="optional"/> + <xsd:attribute name="lvl" type="ST_TextIndentLevelType" use="optional"/> + <xsd:attribute name="indent" type="ST_TextIndent" use="optional"/> + <xsd:attribute name="algn" type="ST_TextAlignType" use="optional"/> + <xsd:attribute name="defTabSz" type="ST_Coordinate32" use="optional"/> + <xsd:attribute name="rtl" type="xsd:boolean" use="optional"/> + <xsd:attribute name="eaLnBrk" type="xsd:boolean" use="optional"/> + <xsd:attribute name="fontAlgn" type="ST_TextFontAlignType" use="optional"/> + <xsd:attribute name="latinLnBrk" type="xsd:boolean" use="optional"/> + <xsd:attribute name="hangingPunct" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TextField"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="t" type="xsd:string" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="s:ST_Guid" use="required"/> + <xsd:attribute name="type" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:group name="EG_TextRun"> + <xsd:choice> + <xsd:element name="r" type="CT_RegularTextRun"/> + <xsd:element name="br" type="CT_TextLineBreak"/> + <xsd:element name="fld" type="CT_TextField"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_RegularTextRun"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="t" type="xsd:string" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd new file mode 100644 index 0000000..1dbf051 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..f1af17d --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..0a185ab --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd new file mode 100644 index 0000000..14ef488 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd @@ -0,0 +1,1676 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://schemas.openxmlformats.org/presentationml/2006/main" + xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" + xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + elementFormDefault="qualified" + targetNamespace="http://schemas.openxmlformats.org/presentationml/2006/main"> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + schemaLocation="shared-relationshipReference.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main" + schemaLocation="dml-main.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + schemaLocation="shared-commonSimpleTypes.xsd"/> + <xsd:simpleType name="ST_TransitionSideDirectionType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="l"/> + <xsd:enumeration value="u"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="d"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TransitionCornerDirectionType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="lu"/> + <xsd:enumeration value="ru"/> + <xsd:enumeration value="ld"/> + <xsd:enumeration value="rd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TransitionInOutDirectionType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="out"/> + <xsd:enumeration value="in"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SideDirectionTransition"> + <xsd:attribute name="dir" type="ST_TransitionSideDirectionType" use="optional" default="l"/> + </xsd:complexType> + <xsd:complexType name="CT_CornerDirectionTransition"> + <xsd:attribute name="dir" type="ST_TransitionCornerDirectionType" use="optional" default="lu"/> + </xsd:complexType> + <xsd:simpleType name="ST_TransitionEightDirectionType"> + <xsd:union memberTypes="ST_TransitionSideDirectionType ST_TransitionCornerDirectionType"/> + </xsd:simpleType> + <xsd:complexType name="CT_EightDirectionTransition"> + <xsd:attribute name="dir" type="ST_TransitionEightDirectionType" use="optional" default="l"/> + </xsd:complexType> + <xsd:complexType name="CT_OrientationTransition"> + <xsd:attribute name="dir" type="ST_Direction" use="optional" default="horz"/> + </xsd:complexType> + <xsd:complexType name="CT_InOutTransition"> + <xsd:attribute name="dir" type="ST_TransitionInOutDirectionType" use="optional" default="out"/> + </xsd:complexType> + <xsd:complexType name="CT_OptionalBlackTransition"> + <xsd:attribute name="thruBlk" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_SplitTransition"> + <xsd:attribute name="orient" type="ST_Direction" use="optional" default="horz"/> + <xsd:attribute name="dir" type="ST_TransitionInOutDirectionType" use="optional" default="out"/> + </xsd:complexType> + <xsd:complexType name="CT_WheelTransition"> + <xsd:attribute name="spokes" type="xsd:unsignedInt" use="optional" default="4"/> + </xsd:complexType> + <xsd:complexType name="CT_TransitionStartSoundAction"> + <xsd:sequence> + <xsd:element minOccurs="1" maxOccurs="1" name="snd" type="a:CT_EmbeddedWAVAudioFile"/> + </xsd:sequence> + <xsd:attribute name="loop" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_TransitionSoundAction"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="stSnd" type="CT_TransitionStartSoundAction"/> + <xsd:element name="endSnd" type="CT_Empty"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TransitionSpeed"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="slow"/> + <xsd:enumeration value="med"/> + <xsd:enumeration value="fast"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideTransition"> + <xsd:sequence> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="blinds" type="CT_OrientationTransition"/> + <xsd:element name="checker" type="CT_OrientationTransition"/> + <xsd:element name="circle" type="CT_Empty"/> + <xsd:element name="dissolve" type="CT_Empty"/> + <xsd:element name="comb" type="CT_OrientationTransition"/> + <xsd:element name="cover" type="CT_EightDirectionTransition"/> + <xsd:element name="cut" type="CT_OptionalBlackTransition"/> + <xsd:element name="diamond" type="CT_Empty"/> + <xsd:element name="fade" type="CT_OptionalBlackTransition"/> + <xsd:element name="newsflash" type="CT_Empty"/> + <xsd:element name="plus" type="CT_Empty"/> + <xsd:element name="pull" type="CT_EightDirectionTransition"/> + <xsd:element name="push" type="CT_SideDirectionTransition"/> + <xsd:element name="random" type="CT_Empty"/> + <xsd:element name="randomBar" type="CT_OrientationTransition"/> + <xsd:element name="split" type="CT_SplitTransition"/> + <xsd:element name="strips" type="CT_CornerDirectionTransition"/> + <xsd:element name="wedge" type="CT_Empty"/> + <xsd:element name="wheel" type="CT_WheelTransition"/> + <xsd:element name="wipe" type="CT_SideDirectionTransition"/> + <xsd:element name="zoom" type="CT_InOutTransition"/> + </xsd:choice> + <xsd:element name="sndAc" minOccurs="0" maxOccurs="1" type="CT_TransitionSoundAction"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="spd" type="ST_TransitionSpeed" use="optional" default="fast"/> + <xsd:attribute name="advClick" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="advTm" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLTimeIndefinite"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="indefinite"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTime"> + <xsd:union memberTypes="xsd:unsignedInt ST_TLTimeIndefinite"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeID"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:complexType name="CT_TLIterateIntervalTime"> + <xsd:attribute name="val" type="ST_TLTime" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLIterateIntervalPercentage"> + <xsd:attribute name="val" type="a:ST_PositivePercentage" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_IterateType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="el"/> + <xsd:enumeration value="wd"/> + <xsd:enumeration value="lt"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLIterateData"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="tmAbs" type="CT_TLIterateIntervalTime"/> + <xsd:element name="tmPct" type="CT_TLIterateIntervalPercentage"/> + </xsd:choice> + <xsd:attribute name="type" type="ST_IterateType" use="optional" default="el"/> + <xsd:attribute name="backwards" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_TLSubShapeId"> + <xsd:attribute name="spid" type="a:ST_ShapeID" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTextTargetElement"> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="charRg" type="CT_IndexRange"/> + <xsd:element name="pRg" type="CT_IndexRange"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TLChartSubelementType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="gridLegend"/> + <xsd:enumeration value="series"/> + <xsd:enumeration value="category"/> + <xsd:enumeration value="ptInSeries"/> + <xsd:enumeration value="ptInCategory"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLOleChartTargetElement"> + <xsd:attribute name="type" type="ST_TLChartSubelementType" use="required"/> + <xsd:attribute name="lvl" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_TLShapeTargetElement"> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="bg" type="CT_Empty"/> + <xsd:element name="subSp" type="CT_TLSubShapeId"/> + <xsd:element name="oleChartEl" type="CT_TLOleChartTargetElement"/> + <xsd:element name="txEl" type="CT_TLTextTargetElement"/> + <xsd:element name="graphicEl" type="a:CT_AnimationElementChoice"/> + </xsd:choice> + <xsd:attribute name="spid" type="a:ST_DrawingElementId" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTimeTargetElement"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="sldTgt" type="CT_Empty"/> + <xsd:element name="sndTgt" type="a:CT_EmbeddedWAVAudioFile"/> + <xsd:element name="spTgt" type="CT_TLShapeTargetElement"/> + <xsd:element name="inkTgt" type="CT_TLSubShapeId"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_TLTriggerTimeNodeID"> + <xsd:attribute name="val" type="ST_TLTimeNodeID" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLTriggerRuntimeNode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="first"/> + <xsd:enumeration value="last"/> + <xsd:enumeration value="all"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLTriggerRuntimeNode"> + <xsd:attribute name="val" type="ST_TLTriggerRuntimeNode" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLTriggerEvent"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="onBegin"/> + <xsd:enumeration value="onEnd"/> + <xsd:enumeration value="begin"/> + <xsd:enumeration value="end"/> + <xsd:enumeration value="onClick"/> + <xsd:enumeration value="onDblClick"/> + <xsd:enumeration value="onMouseOver"/> + <xsd:enumeration value="onMouseOut"/> + <xsd:enumeration value="onNext"/> + <xsd:enumeration value="onPrev"/> + <xsd:enumeration value="onStopAudio"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLTimeCondition"> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="tgtEl" type="CT_TLTimeTargetElement"/> + <xsd:element name="tn" type="CT_TLTriggerTimeNodeID"/> + <xsd:element name="rtn" type="CT_TLTriggerRuntimeNode"/> + </xsd:choice> + <xsd:attribute name="evt" use="optional" type="ST_TLTriggerEvent"/> + <xsd:attribute name="delay" type="ST_TLTime" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTimeConditionList"> + <xsd:sequence> + <xsd:element name="cond" type="CT_TLTimeCondition" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TimeNodeList"> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="par" type="CT_TLTimeNodeParallel"/> + <xsd:element name="seq" type="CT_TLTimeNodeSequence"/> + <xsd:element name="excl" type="CT_TLTimeNodeExclusive"/> + <xsd:element name="anim" type="CT_TLAnimateBehavior"/> + <xsd:element name="animClr" type="CT_TLAnimateColorBehavior"/> + <xsd:element name="animEffect" type="CT_TLAnimateEffectBehavior"/> + <xsd:element name="animMotion" type="CT_TLAnimateMotionBehavior"/> + <xsd:element name="animRot" type="CT_TLAnimateRotationBehavior"/> + <xsd:element name="animScale" type="CT_TLAnimateScaleBehavior"/> + <xsd:element name="cmd" type="CT_TLCommandBehavior"/> + <xsd:element name="set" type="CT_TLSetBehavior"/> + <xsd:element name="audio" type="CT_TLMediaNodeAudio"/> + <xsd:element name="video" type="CT_TLMediaNodeVideo"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TLTimeNodePresetClassType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="entr"/> + <xsd:enumeration value="exit"/> + <xsd:enumeration value="emph"/> + <xsd:enumeration value="path"/> + <xsd:enumeration value="verb"/> + <xsd:enumeration value="mediacall"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeRestartType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="always"/> + <xsd:enumeration value="whenNotActive"/> + <xsd:enumeration value="never"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeFillType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="remove"/> + <xsd:enumeration value="freeze"/> + <xsd:enumeration value="hold"/> + <xsd:enumeration value="transition"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeSyncType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="canSlip"/> + <xsd:enumeration value="locked"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeMasterRelation"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sameClick"/> + <xsd:enumeration value="lastClick"/> + <xsd:enumeration value="nextClick"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLTimeNodeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="clickEffect"/> + <xsd:enumeration value="withEffect"/> + <xsd:enumeration value="afterEffect"/> + <xsd:enumeration value="mainSeq"/> + <xsd:enumeration value="interactiveSeq"/> + <xsd:enumeration value="clickPar"/> + <xsd:enumeration value="withGroup"/> + <xsd:enumeration value="afterGroup"/> + <xsd:enumeration value="tmRoot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLCommonTimeNodeData"> + <xsd:sequence> + <xsd:element name="stCondLst" type="CT_TLTimeConditionList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="endCondLst" type="CT_TLTimeConditionList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="endSync" type="CT_TLTimeCondition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="iterate" type="CT_TLIterateData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="childTnLst" type="CT_TimeNodeList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="subTnLst" type="CT_TimeNodeList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_TLTimeNodeID" use="optional"/> + <xsd:attribute name="presetID" type="xsd:int" use="optional"/> + <xsd:attribute name="presetClass" type="ST_TLTimeNodePresetClassType" use="optional"/> + <xsd:attribute name="presetSubtype" type="xsd:int" use="optional"/> + <xsd:attribute name="dur" type="ST_TLTime" use="optional"/> + <xsd:attribute name="repeatCount" type="ST_TLTime" use="optional" default="1000"/> + <xsd:attribute name="repeatDur" type="ST_TLTime" use="optional"/> + <xsd:attribute name="spd" type="a:ST_Percentage" use="optional" default="100%"/> + <xsd:attribute name="accel" type="a:ST_PositiveFixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="decel" type="a:ST_PositiveFixedPercentage" use="optional" default="0%"/> + <xsd:attribute name="autoRev" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="restart" type="ST_TLTimeNodeRestartType" use="optional"/> + <xsd:attribute name="fill" type="ST_TLTimeNodeFillType" use="optional"/> + <xsd:attribute name="syncBehavior" type="ST_TLTimeNodeSyncType" use="optional"/> + <xsd:attribute name="tmFilter" type="xsd:string" use="optional"/> + <xsd:attribute name="evtFilter" type="xsd:string" use="optional"/> + <xsd:attribute name="display" type="xsd:boolean" use="optional"/> + <xsd:attribute name="masterRel" type="ST_TLTimeNodeMasterRelation" use="optional"/> + <xsd:attribute name="bldLvl" type="xsd:int" use="optional"/> + <xsd:attribute name="grpId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="afterEffect" type="xsd:boolean" use="optional"/> + <xsd:attribute name="nodeType" type="ST_TLTimeNodeType" use="optional"/> + <xsd:attribute name="nodePh" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTimeNodeParallel"> + <xsd:sequence> + <xsd:element name="cTn" type="CT_TLCommonTimeNodeData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TLNextActionType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="seek"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLPreviousActionType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="skipTimed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLTimeNodeSequence"> + <xsd:sequence> + <xsd:element name="cTn" type="CT_TLCommonTimeNodeData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="prevCondLst" type="CT_TLTimeConditionList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="nextCondLst" type="CT_TLTimeConditionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="concurrent" type="xsd:boolean" use="optional"/> + <xsd:attribute name="prevAc" type="ST_TLPreviousActionType" use="optional"/> + <xsd:attribute name="nextAc" type="ST_TLNextActionType" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTimeNodeExclusive"> + <xsd:sequence> + <xsd:element name="cTn" type="CT_TLCommonTimeNodeData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TLBehaviorAttributeNameList"> + <xsd:sequence> + <xsd:element name="attrName" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TLBehaviorAdditiveType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="base"/> + <xsd:enumeration value="sum"/> + <xsd:enumeration value="repl"/> + <xsd:enumeration value="mult"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLBehaviorAccumulateType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="always"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLBehaviorTransformType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pt"/> + <xsd:enumeration value="img"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLBehaviorOverrideType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="childStyle"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLCommonBehaviorData"> + <xsd:sequence> + <xsd:element name="cTn" type="CT_TLCommonTimeNodeData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tgtEl" type="CT_TLTimeTargetElement" minOccurs="1" maxOccurs="1"/> + <xsd:element name="attrNameLst" type="CT_TLBehaviorAttributeNameList" minOccurs="0" + maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="additive" type="ST_TLBehaviorAdditiveType" use="optional"/> + <xsd:attribute name="accumulate" type="ST_TLBehaviorAccumulateType" use="optional"/> + <xsd:attribute name="xfrmType" type="ST_TLBehaviorTransformType" use="optional"/> + <xsd:attribute name="from" type="xsd:string" use="optional"/> + <xsd:attribute name="to" type="xsd:string" use="optional"/> + <xsd:attribute name="by" type="xsd:string" use="optional"/> + <xsd:attribute name="rctx" type="xsd:string" use="optional"/> + <xsd:attribute name="override" type="ST_TLBehaviorOverrideType" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimVariantBooleanVal"> + <xsd:attribute name="val" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimVariantIntegerVal"> + <xsd:attribute name="val" type="xsd:int" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimVariantFloatVal"> + <xsd:attribute name="val" type="xsd:float" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimVariantStringVal"> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimVariant"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="boolVal" type="CT_TLAnimVariantBooleanVal"/> + <xsd:element name="intVal" type="CT_TLAnimVariantIntegerVal"/> + <xsd:element name="fltVal" type="CT_TLAnimVariantFloatVal"/> + <xsd:element name="strVal" type="CT_TLAnimVariantStringVal"/> + <xsd:element name="clrVal" type="a:CT_Color"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TLTimeAnimateValueTime"> + <xsd:union memberTypes="a:ST_PositiveFixedPercentage ST_TLTimeIndefinite"/> + </xsd:simpleType> + <xsd:complexType name="CT_TLTimeAnimateValue"> + <xsd:sequence> + <xsd:element name="val" type="CT_TLAnimVariant" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="tm" type="ST_TLTimeAnimateValueTime" use="optional" default="indefinite"/> + <xsd:attribute name="fmla" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_TLTimeAnimateValueList"> + <xsd:sequence> + <xsd:element name="tav" type="CT_TLTimeAnimateValue" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TLAnimateBehaviorCalcMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="discrete"/> + <xsd:enumeration value="lin"/> + <xsd:enumeration value="fmla"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLAnimateBehaviorValueType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="str"/> + <xsd:enumeration value="num"/> + <xsd:enumeration value="clr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLAnimateBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tavLst" type="CT_TLTimeAnimateValueList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="by" type="xsd:string" use="optional"/> + <xsd:attribute name="from" type="xsd:string" use="optional"/> + <xsd:attribute name="to" type="xsd:string" use="optional"/> + <xsd:attribute name="calcmode" type="ST_TLAnimateBehaviorCalcMode" use="optional"/> + <xsd:attribute name="valueType" type="ST_TLAnimateBehaviorValueType" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLByRgbColorTransform"> + <xsd:attribute name="r" type="a:ST_FixedPercentage" use="required"/> + <xsd:attribute name="g" type="a:ST_FixedPercentage" use="required"/> + <xsd:attribute name="b" type="a:ST_FixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLByHslColorTransform"> + <xsd:attribute name="h" type="a:ST_Angle" use="required"/> + <xsd:attribute name="s" type="a:ST_FixedPercentage" use="required"/> + <xsd:attribute name="l" type="a:ST_FixedPercentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLByAnimateColorTransform"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="rgb" type="CT_TLByRgbColorTransform"/> + <xsd:element name="hsl" type="CT_TLByHslColorTransform"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_TLAnimateColorSpace"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="rgb"/> + <xsd:enumeration value="hsl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLAnimateColorDirection"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="cw"/> + <xsd:enumeration value="ccw"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLAnimateColorBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="by" type="CT_TLByAnimateColorTransform" minOccurs="0" maxOccurs="1"/> + <xsd:element name="from" type="a:CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="to" type="a:CT_Color" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="clrSpc" type="ST_TLAnimateColorSpace" use="optional"/> + <xsd:attribute name="dir" type="ST_TLAnimateColorDirection" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLAnimateEffectTransition"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="in"/> + <xsd:enumeration value="out"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLAnimateEffectBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="progress" type="CT_TLAnimVariant" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="transition" type="ST_TLAnimateEffectTransition" default="in" use="optional"/> + <xsd:attribute name="filter" type="xsd:string" use="optional"/> + <xsd:attribute name="prLst" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLAnimateMotionBehaviorOrigin"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="parent"/> + <xsd:enumeration value="layout"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TLAnimateMotionPathEditMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="relative"/> + <xsd:enumeration value="fixed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLPoint"> + <xsd:attribute name="x" type="a:ST_Percentage" use="required"/> + <xsd:attribute name="y" type="a:ST_Percentage" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimateMotionBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="by" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + <xsd:element name="from" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + <xsd:element name="to" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rCtr" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="origin" type="ST_TLAnimateMotionBehaviorOrigin" use="optional"/> + <xsd:attribute name="path" type="xsd:string" use="optional"/> + <xsd:attribute name="pathEditMode" type="ST_TLAnimateMotionPathEditMode" use="optional"/> + <xsd:attribute name="rAng" type="a:ST_Angle" use="optional"/> + <xsd:attribute name="ptsTypes" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimateRotationBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="by" type="a:ST_Angle" use="optional"/> + <xsd:attribute name="from" type="a:ST_Angle" use="optional"/> + <xsd:attribute name="to" type="a:ST_Angle" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLAnimateScaleBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="by" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + <xsd:element name="from" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + <xsd:element name="to" type="CT_TLPoint" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="zoomContents" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLCommandType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="evt"/> + <xsd:enumeration value="call"/> + <xsd:enumeration value="verb"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLCommandBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute type="ST_TLCommandType" name="type" use="optional"/> + <xsd:attribute name="cmd" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TLSetBehavior"> + <xsd:sequence> + <xsd:element name="cBhvr" type="CT_TLCommonBehaviorData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="to" type="CT_TLAnimVariant" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TLCommonMediaNodeData"> + <xsd:sequence> + <xsd:element name="cTn" type="CT_TLCommonTimeNodeData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tgtEl" type="CT_TLTimeTargetElement" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="vol" type="a:ST_PositiveFixedPercentage" default="50%" use="optional"/> + <xsd:attribute name="mute" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="numSld" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="showWhenStopped" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_TLMediaNodeAudio"> + <xsd:sequence> + <xsd:element name="cMediaNode" type="CT_TLCommonMediaNodeData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="isNarration" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_TLMediaNodeVideo"> + <xsd:sequence> + <xsd:element name="cMediaNode" type="CT_TLCommonMediaNodeData" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="fullScrn" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:attributeGroup name="AG_TLBuild"> + <xsd:attribute name="spid" type="a:ST_DrawingElementId" use="required"/> + <xsd:attribute name="grpId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="uiExpand" type="xsd:boolean" use="optional" default="false"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_TLTemplate"> + <xsd:sequence> + <xsd:element name="tnLst" type="CT_TimeNodeList" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="lvl" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_TLTemplateList"> + <xsd:sequence> + <xsd:element name="tmpl" type="CT_TLTemplate" minOccurs="0" maxOccurs="9"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TLParaBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="allAtOnce"/> + <xsd:enumeration value="p"/> + <xsd:enumeration value="cust"/> + <xsd:enumeration value="whole"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLBuildParagraph"> + <xsd:sequence> + <xsd:element name="tmplLst" type="CT_TLTemplateList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_TLBuild"/> + <xsd:attribute name="build" type="ST_TLParaBuildType" use="optional" default="whole"/> + <xsd:attribute name="bldLvl" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="animBg" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoUpdateAnimBg" type="xsd:boolean" default="true" use="optional"/> + <xsd:attribute name="rev" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="advAuto" type="ST_TLTime" use="optional" default="indefinite"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLDiagramBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="whole"/> + <xsd:enumeration value="depthByNode"/> + <xsd:enumeration value="depthByBranch"/> + <xsd:enumeration value="breadthByNode"/> + <xsd:enumeration value="breadthByLvl"/> + <xsd:enumeration value="cw"/> + <xsd:enumeration value="cwIn"/> + <xsd:enumeration value="cwOut"/> + <xsd:enumeration value="ccw"/> + <xsd:enumeration value="ccwIn"/> + <xsd:enumeration value="ccwOut"/> + <xsd:enumeration value="inByRing"/> + <xsd:enumeration value="outByRing"/> + <xsd:enumeration value="up"/> + <xsd:enumeration value="down"/> + <xsd:enumeration value="allAtOnce"/> + <xsd:enumeration value="cust"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLBuildDiagram"> + <xsd:attributeGroup ref="AG_TLBuild"/> + <xsd:attribute name="bld" type="ST_TLDiagramBuildType" use="optional" default="whole"/> + </xsd:complexType> + <xsd:simpleType name="ST_TLOleChartBuildType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="allAtOnce"/> + <xsd:enumeration value="series"/> + <xsd:enumeration value="category"/> + <xsd:enumeration value="seriesEl"/> + <xsd:enumeration value="categoryEl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TLOleBuildChart"> + <xsd:attributeGroup ref="AG_TLBuild"/> + <xsd:attribute name="bld" type="ST_TLOleChartBuildType" use="optional" default="allAtOnce"/> + <xsd:attribute name="animBg" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_TLGraphicalObjectBuild"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="bldAsOne" type="CT_Empty"/> + <xsd:element name="bldSub" type="a:CT_AnimationGraphicalObjectBuildProperties"/> + </xsd:choice> + <xsd:attributeGroup ref="AG_TLBuild"/> + </xsd:complexType> + <xsd:complexType name="CT_BuildList"> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="bldP" type="CT_TLBuildParagraph"/> + <xsd:element name="bldDgm" type="CT_TLBuildDiagram"/> + <xsd:element name="bldOleChart" type="CT_TLOleBuildChart"/> + <xsd:element name="bldGraphic" type="CT_TLGraphicalObjectBuild"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_SlideTiming"> + <xsd:sequence> + <xsd:element name="tnLst" type="CT_TimeNodeList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bldLst" type="CT_BuildList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Empty"/> + <xsd:simpleType name="ST_Name"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Direction"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="horz"/> + <xsd:enumeration value="vert"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Index"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:complexType name="CT_IndexRange"> + <xsd:attribute name="st" type="ST_Index" use="required"/> + <xsd:attribute name="end" type="ST_Index" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideRelationshipListEntry"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideRelationshipList"> + <xsd:sequence> + <xsd:element name="sld" type="CT_SlideRelationshipListEntry" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomShowId"> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:group name="EG_SlideListChoice"> + <xsd:choice> + <xsd:element name="sldAll" type="CT_Empty"/> + <xsd:element name="sldRg" type="CT_IndexRange"/> + <xsd:element name="custShow" type="CT_CustomShowId"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_CustomerData"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TagsData"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomerDataList"> + <xsd:sequence minOccurs="0" maxOccurs="1"> + <xsd:element name="custData" type="CT_CustomerData" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="tags" type="CT_TagsData" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Extension"> + <xsd:sequence> + <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="xsd:token" use="required"/> + </xsd:complexType> + <xsd:group name="EG_ExtensionList"> + <xsd:sequence> + <xsd:element name="ext" type="CT_Extension" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_ExtensionList"> + <xsd:sequence> + <xsd:group ref="EG_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExtensionListModify"> + <xsd:sequence> + <xsd:group ref="EG_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="mod" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CommentAuthor"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="name" type="ST_Name" use="required"/> + <xsd:attribute name="initials" type="ST_Name" use="required"/> + <xsd:attribute name="lastIdx" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="clrIdx" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CommentAuthorList"> + <xsd:sequence> + <xsd:element name="cmAuthor" type="CT_CommentAuthor" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="cmAuthorLst" type="CT_CommentAuthorList"/> + <xsd:complexType name="CT_Comment"> + <xsd:sequence> + <xsd:element name="pos" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="text" type="xsd:string" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="authorId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="dt" type="xsd:dateTime" use="optional"/> + <xsd:attribute name="idx" type="ST_Index" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CommentList"> + <xsd:sequence> + <xsd:element name="cm" type="CT_Comment" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="cmLst" type="CT_CommentList"/> + <xsd:attributeGroup name="AG_Ole"> + <xsd:attribute name="spid" type="a:ST_ShapeID" use="optional"/> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="showAsIcon" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute ref="r:id" use="optional"/> + <xsd:attribute name="imgW" type="a:ST_PositiveCoordinate32" use="optional"/> + <xsd:attribute name="imgH" type="a:ST_PositiveCoordinate32" use="optional"/> + </xsd:attributeGroup> + <xsd:simpleType name="ST_OleObjectFollowColorScheme"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="full"/> + <xsd:enumeration value="textAndBackground"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_OleObjectEmbed"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="followColorScheme" type="ST_OleObjectFollowColorScheme" use="optional" + default="none"/> + </xsd:complexType> + <xsd:complexType name="CT_OleObjectLink"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="updateAutomatic" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_OleObject"> + <xsd:sequence> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="embed" type="CT_OleObjectEmbed"/> + <xsd:element name="link" type="CT_OleObjectLink"/> + </xsd:choice> + <xsd:element name="pic" type="CT_Picture" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Ole"/> + <xsd:attribute name="progId" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:element name="oleObj" type="CT_OleObject"/> + <xsd:complexType name="CT_Control"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pic" type="CT_Picture" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_Ole"/> + </xsd:complexType> + <xsd:complexType name="CT_ControlList"> + <xsd:sequence> + <xsd:element name="control" type="CT_Control" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_SlideId"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="256"/> + <xsd:maxExclusive value="2147483648"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideIdListEntry"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_SlideId" use="required"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideIdList"> + <xsd:sequence> + <xsd:element name="sldId" type="CT_SlideIdListEntry" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_SlideMasterId"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="2147483648"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideMasterIdListEntry"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_SlideMasterId" use="optional"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideMasterIdList"> + <xsd:sequence> + <xsd:element name="sldMasterId" type="CT_SlideMasterIdListEntry" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NotesMasterIdListEntry"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_NotesMasterIdList"> + <xsd:sequence> + <xsd:element name="notesMasterId" type="CT_NotesMasterIdListEntry" minOccurs="0" maxOccurs="1" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_HandoutMasterIdListEntry"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_HandoutMasterIdList"> + <xsd:sequence> + <xsd:element name="handoutMasterId" type="CT_HandoutMasterIdListEntry" minOccurs="0" + maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EmbeddedFontDataId"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_EmbeddedFontListEntry"> + <xsd:sequence> + <xsd:element name="font" type="a:CT_TextFont" minOccurs="1" maxOccurs="1"/> + <xsd:element name="regular" type="CT_EmbeddedFontDataId" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bold" type="CT_EmbeddedFontDataId" minOccurs="0" maxOccurs="1"/> + <xsd:element name="italic" type="CT_EmbeddedFontDataId" minOccurs="0" maxOccurs="1"/> + <xsd:element name="boldItalic" type="CT_EmbeddedFontDataId" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EmbeddedFontList"> + <xsd:sequence> + <xsd:element name="embeddedFont" type="CT_EmbeddedFontListEntry" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SmartTags"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomShow"> + <xsd:sequence> + <xsd:element name="sldLst" type="CT_SlideRelationshipList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="ST_Name" use="required"/> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomShowList"> + <xsd:sequence> + <xsd:element name="custShow" type="CT_CustomShow" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_PhotoAlbumLayout"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="fitToSlide"/> + <xsd:enumeration value="1pic"/> + <xsd:enumeration value="2pic"/> + <xsd:enumeration value="4pic"/> + <xsd:enumeration value="1picTitle"/> + <xsd:enumeration value="2picTitle"/> + <xsd:enumeration value="4picTitle"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PhotoAlbumFrameShape"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="frameStyle1"/> + <xsd:enumeration value="frameStyle2"/> + <xsd:enumeration value="frameStyle3"/> + <xsd:enumeration value="frameStyle4"/> + <xsd:enumeration value="frameStyle5"/> + <xsd:enumeration value="frameStyle6"/> + <xsd:enumeration value="frameStyle7"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PhotoAlbum"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="bw" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showCaptions" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="layout" type="ST_PhotoAlbumLayout" use="optional" default="fitToSlide"/> + <xsd:attribute name="frame" type="ST_PhotoAlbumFrameShape" use="optional" default="frameStyle1" + /> + </xsd:complexType> + <xsd:simpleType name="ST_SlideSizeCoordinate"> + <xsd:restriction base="a:ST_PositiveCoordinate32"> + <xsd:minInclusive value="914400"/> + <xsd:maxInclusive value="51206400"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_SlideSizeType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="screen4x3"/> + <xsd:enumeration value="letter"/> + <xsd:enumeration value="A4"/> + <xsd:enumeration value="35mm"/> + <xsd:enumeration value="overhead"/> + <xsd:enumeration value="banner"/> + <xsd:enumeration value="custom"/> + <xsd:enumeration value="ledger"/> + <xsd:enumeration value="A3"/> + <xsd:enumeration value="B4ISO"/> + <xsd:enumeration value="B5ISO"/> + <xsd:enumeration value="B4JIS"/> + <xsd:enumeration value="B5JIS"/> + <xsd:enumeration value="hagakiCard"/> + <xsd:enumeration value="screen16x9"/> + <xsd:enumeration value="screen16x10"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideSize"> + <xsd:attribute name="cx" type="ST_SlideSizeCoordinate" use="required"/> + <xsd:attribute name="cy" type="ST_SlideSizeCoordinate" use="required"/> + <xsd:attribute name="type" type="ST_SlideSizeType" use="optional" default="custom"/> + </xsd:complexType> + <xsd:complexType name="CT_Kinsoku"> + <xsd:attribute name="lang" type="xsd:string" use="optional"/> + <xsd:attribute name="invalStChars" type="xsd:string" use="required"/> + <xsd:attribute name="invalEndChars" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_BookmarkIdSeed"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="1"/> + <xsd:maxExclusive value="2147483648"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ModifyVerifier"> + <xsd:attribute name="algorithmName" type="xsd:string" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinValue" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cryptProviderType" type="s:ST_CryptProv" use="optional"/> + <xsd:attribute name="cryptAlgorithmClass" type="s:ST_AlgClass" use="optional"/> + <xsd:attribute name="cryptAlgorithmType" type="s:ST_AlgType" use="optional"/> + <xsd:attribute name="cryptAlgorithmSid" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="spinCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="saltData" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="hashData" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="cryptProvider" type="xsd:string" use="optional"/> + <xsd:attribute name="algIdExt" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="algIdExtSource" type="xsd:string" use="optional"/> + <xsd:attribute name="cryptProviderTypeExt" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cryptProviderTypeExtSource" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Presentation"> + <xsd:sequence> + <xsd:element name="sldMasterIdLst" type="CT_SlideMasterIdList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="notesMasterIdLst" type="CT_NotesMasterIdList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="handoutMasterIdLst" type="CT_HandoutMasterIdList" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="sldIdLst" type="CT_SlideIdList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sldSz" type="CT_SlideSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="notesSz" type="a:CT_PositiveSize2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="smartTags" type="CT_SmartTags" minOccurs="0" maxOccurs="1"/> + <xsd:element name="embeddedFontLst" type="CT_EmbeddedFontList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="custShowLst" type="CT_CustomShowList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="photoAlbum" type="CT_PhotoAlbum" minOccurs="0" maxOccurs="1"/> + <xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="kinsoku" type="CT_Kinsoku" minOccurs="0"/> + <xsd:element name="defaultTextStyle" type="a:CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="modifyVerifier" type="CT_ModifyVerifier" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="serverZoom" type="a:ST_Percentage" use="optional" default="50%"/> + <xsd:attribute name="firstSlideNum" type="xsd:int" use="optional" default="1"/> + <xsd:attribute name="showSpecialPlsOnTitleSld" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="rtl" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="removePersonalInfoOnSave" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="compatMode" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="strictFirstAndLastChars" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="embedTrueTypeFonts" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="saveSubsetFonts" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoCompressPictures" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="bookmarkIdSeed" type="ST_BookmarkIdSeed" use="optional" default="1"/> + <xsd:attribute name="conformance" type="s:ST_ConformanceClass"/> + </xsd:complexType> + <xsd:element name="presentation" type="CT_Presentation"/> + <xsd:complexType name="CT_HtmlPublishProperties"> + <xsd:sequence> + <xsd:group ref="EG_SlideListChoice" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="showSpeakerNotes" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="target" type="xsd:string" use="optional"/> + <xsd:attribute name="title" type="xsd:string" use="optional" default=""/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_WebColorType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="browser"/> + <xsd:enumeration value="presentationText"/> + <xsd:enumeration value="presentationAccent"/> + <xsd:enumeration value="whiteTextOnBlack"/> + <xsd:enumeration value="blackTextOnWhite"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_WebScreenSize"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="544x376"/> + <xsd:enumeration value="640x480"/> + <xsd:enumeration value="720x512"/> + <xsd:enumeration value="800x600"/> + <xsd:enumeration value="1024x768"/> + <xsd:enumeration value="1152x882"/> + <xsd:enumeration value="1152x900"/> + <xsd:enumeration value="1280x1024"/> + <xsd:enumeration value="1600x1200"/> + <xsd:enumeration value="1800x1400"/> + <xsd:enumeration value="1920x1200"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_WebEncoding"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:complexType name="CT_WebProperties"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="showAnimation" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="resizeGraphics" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="allowPng" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="relyOnVml" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="organizeInFolders" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="useLongFilenames" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="imgSz" type="ST_WebScreenSize" use="optional" default="800x600"/> + <xsd:attribute name="encoding" type="ST_WebEncoding" use="optional" default=""/> + <xsd:attribute name="clr" type="ST_WebColorType" use="optional" default="whiteTextOnBlack"/> + </xsd:complexType> + <xsd:simpleType name="ST_PrintWhat"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="slides"/> + <xsd:enumeration value="handouts1"/> + <xsd:enumeration value="handouts2"/> + <xsd:enumeration value="handouts3"/> + <xsd:enumeration value="handouts4"/> + <xsd:enumeration value="handouts6"/> + <xsd:enumeration value="handouts9"/> + <xsd:enumeration value="notes"/> + <xsd:enumeration value="outline"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PrintColorMode"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="bw"/> + <xsd:enumeration value="gray"/> + <xsd:enumeration value="clr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PrintProperties"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="prnWhat" type="ST_PrintWhat" use="optional" default="slides"/> + <xsd:attribute name="clrMode" type="ST_PrintColorMode" use="optional" default="clr"/> + <xsd:attribute name="hiddenSlides" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="scaleToFitPaper" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="frameSlides" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ShowInfoBrowse"> + <xsd:attribute name="showScrollbar" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_ShowInfoKiosk"> + <xsd:attribute name="restart" type="xsd:unsignedInt" use="optional" default="300000"/> + </xsd:complexType> + <xsd:group name="EG_ShowType"> + <xsd:choice> + <xsd:element name="present" type="CT_Empty"/> + <xsd:element name="browse" type="CT_ShowInfoBrowse"/> + <xsd:element name="kiosk" type="CT_ShowInfoKiosk"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_ShowProperties"> + <xsd:sequence minOccurs="0" maxOccurs="1"> + <xsd:group ref="EG_ShowType" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_SlideListChoice" minOccurs="0" maxOccurs="1"/> + <xsd:element name="penClr" type="a:CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="loop" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showNarration" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showAnimation" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="useTimings" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_PresentationProperties"> + <xsd:sequence> + <xsd:element name="htmlPubPr" type="CT_HtmlPublishProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="webPr" type="CT_WebProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="prnPr" type="CT_PrintProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="showPr" type="CT_ShowProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="clrMru" type="a:CT_ColorMRU" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="presentationPr" type="CT_PresentationProperties"/> + <xsd:complexType name="CT_HeaderFooter"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="sldNum" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="hdr" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="ftr" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="dt" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:simpleType name="ST_PlaceholderType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="title"/> + <xsd:enumeration value="body"/> + <xsd:enumeration value="ctrTitle"/> + <xsd:enumeration value="subTitle"/> + <xsd:enumeration value="dt"/> + <xsd:enumeration value="sldNum"/> + <xsd:enumeration value="ftr"/> + <xsd:enumeration value="hdr"/> + <xsd:enumeration value="obj"/> + <xsd:enumeration value="chart"/> + <xsd:enumeration value="tbl"/> + <xsd:enumeration value="clipArt"/> + <xsd:enumeration value="dgm"/> + <xsd:enumeration value="media"/> + <xsd:enumeration value="sldImg"/> + <xsd:enumeration value="pic"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PlaceholderSize"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="full"/> + <xsd:enumeration value="half"/> + <xsd:enumeration value="quarter"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Placeholder"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_PlaceholderType" use="optional" default="obj"/> + <xsd:attribute name="orient" type="ST_Direction" use="optional" default="horz"/> + <xsd:attribute name="sz" type="ST_PlaceholderSize" use="optional" default="full"/> + <xsd:attribute name="idx" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="hasCustomPrompt" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ApplicationNonVisualDrawingProps"> + <xsd:sequence> + <xsd:element name="ph" type="CT_Placeholder" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="a:EG_Media" minOccurs="0" maxOccurs="1"/> + <xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="isPhoto" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="userDrawn" type="xsd:boolean" use="optional" default="false"/> + </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:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps" 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:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="useBgFill" 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:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps" 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:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </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:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps" 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:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </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:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps" 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:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional"/> + </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:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps" 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:element name="contentPart" type="CT_Rel"/> + </xsd:choice> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Rel"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:group name="EG_TopLevelSlide"> + <xsd:sequence> + <xsd:element name="clrMap" type="a:CT_ColorMapping" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:group name="EG_ChildSlide"> + <xsd:sequence> + <xsd:element name="clrMapOvr" type="a:CT_ColorMappingOverride" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:group> + <xsd:attributeGroup name="AG_ChildSlide"> + <xsd:attribute name="showMasterSp" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showMasterPhAnim" type="xsd:boolean" use="optional" default="true"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_BackgroundProperties"> + <xsd:sequence> + <xsd:group ref="a:EG_FillProperties" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="a:EG_EffectProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="shadeToTitle" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:group name="EG_Background"> + <xsd:choice> + <xsd:element name="bgPr" type="CT_BackgroundProperties"/> + <xsd:element name="bgRef" type="a:CT_StyleMatrixReference"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_Background"> + <xsd:sequence> + <xsd:group ref="EG_Background"/> + </xsd:sequence> + <xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional" default="white"/> + </xsd:complexType> + <xsd:complexType name="CT_CommonSlideData"> + <xsd:sequence> + <xsd:element name="bg" type="CT_Background" minOccurs="0" maxOccurs="1"/> + <xsd:element name="spTree" type="CT_GroupShape" minOccurs="1" maxOccurs="1"/> + <xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="controls" type="CT_ControlList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_Slide"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_ChildSlide" minOccurs="0" maxOccurs="1"/> + <xsd:element name="transition" type="CT_SlideTransition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="timing" type="CT_SlideTiming" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_ChildSlide"/> + <xsd:attribute name="show" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:element name="sld" type="CT_Slide"/> + <xsd:simpleType name="ST_SlideLayoutType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="title"/> + <xsd:enumeration value="tx"/> + <xsd:enumeration value="twoColTx"/> + <xsd:enumeration value="tbl"/> + <xsd:enumeration value="txAndChart"/> + <xsd:enumeration value="chartAndTx"/> + <xsd:enumeration value="dgm"/> + <xsd:enumeration value="chart"/> + <xsd:enumeration value="txAndClipArt"/> + <xsd:enumeration value="clipArtAndTx"/> + <xsd:enumeration value="titleOnly"/> + <xsd:enumeration value="blank"/> + <xsd:enumeration value="txAndObj"/> + <xsd:enumeration value="objAndTx"/> + <xsd:enumeration value="objOnly"/> + <xsd:enumeration value="obj"/> + <xsd:enumeration value="txAndMedia"/> + <xsd:enumeration value="mediaAndTx"/> + <xsd:enumeration value="objOverTx"/> + <xsd:enumeration value="txOverObj"/> + <xsd:enumeration value="txAndTwoObj"/> + <xsd:enumeration value="twoObjAndTx"/> + <xsd:enumeration value="twoObjOverTx"/> + <xsd:enumeration value="fourObj"/> + <xsd:enumeration value="vertTx"/> + <xsd:enumeration value="clipArtAndVertTx"/> + <xsd:enumeration value="vertTitleAndTx"/> + <xsd:enumeration value="vertTitleAndTxOverChart"/> + <xsd:enumeration value="twoObj"/> + <xsd:enumeration value="objAndTwoObj"/> + <xsd:enumeration value="twoObjAndObj"/> + <xsd:enumeration value="cust"/> + <xsd:enumeration value="secHead"/> + <xsd:enumeration value="twoTxTwoObj"/> + <xsd:enumeration value="objTx"/> + <xsd:enumeration value="picTx"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideLayout"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_ChildSlide" minOccurs="0" maxOccurs="1"/> + <xsd:element name="transition" type="CT_SlideTransition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="timing" type="CT_SlideTiming" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_ChildSlide"/> + <xsd:attribute name="matchingName" type="xsd:string" use="optional" default=""/> + <xsd:attribute name="type" type="ST_SlideLayoutType" use="optional" default="cust"/> + <xsd:attribute name="preserve" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="userDrawn" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:element name="sldLayout" type="CT_SlideLayout"/> + <xsd:complexType name="CT_SlideMasterTextStyles"> + <xsd:sequence> + <xsd:element name="titleStyle" type="a:CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bodyStyle" type="a:CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="otherStyle" type="a:CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_SlideLayoutId"> + <xsd:restriction base="xsd:unsignedInt"> + <xsd:minInclusive value="2147483648"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SlideLayoutIdListEntry"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_SlideLayoutId" use="optional"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideLayoutIdList"> + <xsd:sequence> + <xsd:element name="sldLayoutId" type="CT_SlideLayoutIdListEntry" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SlideMaster"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_TopLevelSlide" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sldLayoutIdLst" type="CT_SlideLayoutIdList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="transition" type="CT_SlideTransition" minOccurs="0" maxOccurs="1"/> + <xsd:element name="timing" type="CT_SlideTiming" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="txStyles" type="CT_SlideMasterTextStyles" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="preserve" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:element name="sldMaster" type="CT_SlideMaster"/> + <xsd:complexType name="CT_HandoutMaster"> + <xsd:sequence> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_TopLevelSlide" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="handoutMaster" type="CT_HandoutMaster"/> + <xsd:complexType name="CT_NotesMaster"> + <xsd:sequence> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_TopLevelSlide" minOccurs="1" maxOccurs="1"/> + <xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="notesStyle" type="a:CT_TextListStyle" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="notesMaster" type="CT_NotesMaster"/> + <xsd:complexType name="CT_NotesSlide"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cSld" type="CT_CommonSlideData" minOccurs="1" maxOccurs="1"/> + <xsd:group ref="EG_ChildSlide" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_ChildSlide"/> + </xsd:complexType> + <xsd:element name="notes" type="CT_NotesSlide"/> + <xsd:complexType name="CT_SlideSyncProperties"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="serverSldId" type="xsd:string" use="required"/> + <xsd:attribute name="serverSldModifiedTime" type="xsd:dateTime" use="required"/> + <xsd:attribute name="clientInsertedTime" type="xsd:dateTime" use="required"/> + </xsd:complexType> + <xsd:element name="sldSyncPr" type="CT_SlideSyncProperties"/> + <xsd:complexType name="CT_StringTag"> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="val" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TagList"> + <xsd:sequence> + <xsd:element name="tag" type="CT_StringTag" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="tagLst" type="CT_TagList"/> + <xsd:simpleType name="ST_SplitterBarState"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="minimized"/> + <xsd:enumeration value="restored"/> + <xsd:enumeration value="maximized"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ViewType"> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="sldView"/> + <xsd:enumeration value="sldMasterView"/> + <xsd:enumeration value="notesView"/> + <xsd:enumeration value="handoutView"/> + <xsd:enumeration value="notesMasterView"/> + <xsd:enumeration value="outlineView"/> + <xsd:enumeration value="sldSorterView"/> + <xsd:enumeration value="sldThumbnailView"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_NormalViewPortion"> + <xsd:attribute name="sz" type="a:ST_PositiveFixedPercentage" use="required"/> + <xsd:attribute name="autoAdjust" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_NormalViewProperties"> + <xsd:sequence> + <xsd:element name="restoredLeft" type="CT_NormalViewPortion" minOccurs="1" maxOccurs="1"/> + <xsd:element name="restoredTop" type="CT_NormalViewPortion" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="showOutlineIcons" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="snapVertSplitter" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="vertBarState" type="ST_SplitterBarState" use="optional" default="restored"/> + <xsd:attribute name="horzBarState" type="ST_SplitterBarState" use="optional" default="restored"/> + <xsd:attribute name="preferSingleView" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CommonViewProperties"> + <xsd:sequence> + <xsd:element name="scale" type="a:CT_Scale2D" minOccurs="1" maxOccurs="1"/> + <xsd:element name="origin" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="varScale" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_NotesTextViewProperties"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cViewPr" type="CT_CommonViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OutlineViewSlideEntry"> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="collapse" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_OutlineViewSlideList"> + <xsd:sequence> + <xsd:element name="sld" type="CT_OutlineViewSlideEntry" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OutlineViewProperties"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cViewPr" type="CT_CommonViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sldLst" type="CT_OutlineViewSlideList" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SlideSorterViewProperties"> + <xsd:sequence minOccurs="1" maxOccurs="1"> + <xsd:element name="cViewPr" type="CT_CommonViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="showFormatting" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_Guide"> + <xsd:attribute name="orient" type="ST_Direction" use="optional" default="vert"/> + <xsd:attribute name="pos" type="a:ST_Coordinate32" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_GuideList"> + <xsd:sequence minOccurs="0" maxOccurs="1"> + <xsd:element name="guide" type="CT_Guide" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CommonSlideViewProperties"> + <xsd:sequence> + <xsd:element name="cViewPr" type="CT_CommonViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="guideLst" type="CT_GuideList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="snapToGrid" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="snapToObjects" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showGuides" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_SlideViewProperties"> + <xsd:sequence> + <xsd:element name="cSldViewPr" type="CT_CommonSlideViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NotesViewProperties"> + <xsd:sequence> + <xsd:element name="cSldViewPr" type="CT_CommonSlideViewProperties" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ViewProperties"> + <xsd:sequence minOccurs="0" maxOccurs="1"> + <xsd:element name="normalViewPr" type="CT_NormalViewProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="slideViewPr" type="CT_SlideViewProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="outlineViewPr" type="CT_OutlineViewProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="notesTextViewPr" type="CT_NotesTextViewProperties" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="sorterViewPr" type="CT_SlideSorterViewProperties" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="notesViewPr" type="CT_NotesViewProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="gridSpacing" type="a:CT_PositiveSize2D" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="lastView" type="ST_ViewType" use="optional" default="sldView"/> + <xsd:attribute name="showComments" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:element name="viewPr" type="CT_ViewProperties"/> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd new file mode 100644 index 0000000..c20f3bf --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd new file mode 100644 index 0000000..ac60252 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd new file mode 100644 index 0000000..424b8ba --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd new file mode 100644 index 0000000..2bddce2 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd new file mode 100644 index 0000000..8a8c18b --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd new file mode 100644 index 0000000..5c42706 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd new file mode 100644 index 0000000..853c341 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd new file mode 100644 index 0000000..da835ee --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd new file mode 100644 index 0000000..87ad265 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd new file mode 100644 index 0000000..9e86f1b --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd new file mode 100644 index 0000000..d0be42e --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd @@ -0,0 +1,4439 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + targetNamespace="http://schemas.openxmlformats.org/spreadsheetml/2006/main" + elementFormDefault="qualified"> + <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:import + namespace="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" + schemaLocation="dml-spreadsheetDrawing.xsd"/> + <xsd:complexType name="CT_AutoFilter"> + <xsd:sequence> + <xsd:element name="filterColumn" minOccurs="0" maxOccurs="unbounded" type="CT_FilterColumn"/> + <xsd:element name="sortState" minOccurs="0" maxOccurs="1" type="CT_SortState"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ref" type="ST_Ref"/> + </xsd:complexType> + <xsd:complexType name="CT_FilterColumn"> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="filters" type="CT_Filters" minOccurs="0" maxOccurs="1"/> + <xsd:element name="top10" type="CT_Top10" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customFilters" type="CT_CustomFilters" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dynamicFilter" type="CT_DynamicFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="colorFilter" type="CT_ColorFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="iconFilter" minOccurs="0" maxOccurs="1" type="CT_IconFilter"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="colId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="hiddenButton" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showButton" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_Filters"> + <xsd:sequence> + <xsd:element name="filter" type="CT_Filter" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="dateGroupItem" type="CT_DateGroupItem" minOccurs="0" maxOccurs="unbounded" + /> + </xsd:sequence> + <xsd:attribute name="blank" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="calendarType" type="s:ST_CalendarType" use="optional" default="none"/> + </xsd:complexType> + <xsd:complexType name="CT_Filter"> + <xsd:attribute name="val" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomFilters"> + <xsd:sequence> + <xsd:element name="customFilter" type="CT_CustomFilter" minOccurs="1" maxOccurs="2"/> + </xsd:sequence> + <xsd:attribute name="and" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomFilter"> + <xsd:attribute name="operator" type="ST_FilterOperator" default="equal" use="optional"/> + <xsd:attribute name="val" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_Top10"> + <xsd:attribute name="top" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="percent" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="val" type="xsd:double" use="required"/> + <xsd:attribute name="filterVal" type="xsd:double" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ColorFilter"> + <xsd:attribute name="dxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="cellColor" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_IconFilter"> + <xsd:attribute name="iconSet" type="ST_IconSetType" use="required"/> + <xsd:attribute name="iconId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_FilterOperator"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="equal"/> + <xsd:enumeration value="lessThan"/> + <xsd:enumeration value="lessThanOrEqual"/> + <xsd:enumeration value="notEqual"/> + <xsd:enumeration value="greaterThanOrEqual"/> + <xsd:enumeration value="greaterThan"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DynamicFilter"> + <xsd:attribute name="type" type="ST_DynamicFilterType" use="required"/> + <xsd:attribute name="val" type="xsd:double" use="optional"/> + <xsd:attribute name="valIso" type="xsd:dateTime" use="optional"/> + <xsd:attribute name="maxVal" type="xsd:double" use="optional"/> + <xsd:attribute name="maxValIso" type="xsd:dateTime" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_DynamicFilterType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="null"/> + <xsd:enumeration value="aboveAverage"/> + <xsd:enumeration value="belowAverage"/> + <xsd:enumeration value="tomorrow"/> + <xsd:enumeration value="today"/> + <xsd:enumeration value="yesterday"/> + <xsd:enumeration value="nextWeek"/> + <xsd:enumeration value="thisWeek"/> + <xsd:enumeration value="lastWeek"/> + <xsd:enumeration value="nextMonth"/> + <xsd:enumeration value="thisMonth"/> + <xsd:enumeration value="lastMonth"/> + <xsd:enumeration value="nextQuarter"/> + <xsd:enumeration value="thisQuarter"/> + <xsd:enumeration value="lastQuarter"/> + <xsd:enumeration value="nextYear"/> + <xsd:enumeration value="thisYear"/> + <xsd:enumeration value="lastYear"/> + <xsd:enumeration value="yearToDate"/> + <xsd:enumeration value="Q1"/> + <xsd:enumeration value="Q2"/> + <xsd:enumeration value="Q3"/> + <xsd:enumeration value="Q4"/> + <xsd:enumeration value="M1"/> + <xsd:enumeration value="M2"/> + <xsd:enumeration value="M3"/> + <xsd:enumeration value="M4"/> + <xsd:enumeration value="M5"/> + <xsd:enumeration value="M6"/> + <xsd:enumeration value="M7"/> + <xsd:enumeration value="M8"/> + <xsd:enumeration value="M9"/> + <xsd:enumeration value="M10"/> + <xsd:enumeration value="M11"/> + <xsd:enumeration value="M12"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_IconSetType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="3Arrows"/> + <xsd:enumeration value="3ArrowsGray"/> + <xsd:enumeration value="3Flags"/> + <xsd:enumeration value="3TrafficLights1"/> + <xsd:enumeration value="3TrafficLights2"/> + <xsd:enumeration value="3Signs"/> + <xsd:enumeration value="3Symbols"/> + <xsd:enumeration value="3Symbols2"/> + <xsd:enumeration value="4Arrows"/> + <xsd:enumeration value="4ArrowsGray"/> + <xsd:enumeration value="4RedToBlack"/> + <xsd:enumeration value="4Rating"/> + <xsd:enumeration value="4TrafficLights"/> + <xsd:enumeration value="5Arrows"/> + <xsd:enumeration value="5ArrowsGray"/> + <xsd:enumeration value="5Rating"/> + <xsd:enumeration value="5Quarters"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SortState"> + <xsd:sequence> + <xsd:element name="sortCondition" minOccurs="0" maxOccurs="64" type="CT_SortCondition"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="columnSort" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="caseSensitive" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="sortMethod" type="ST_SortMethod" use="optional" default="none"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SortCondition"> + <xsd:attribute name="descending" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="sortBy" type="ST_SortBy" use="optional" default="value"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute name="customList" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="dxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="iconSet" type="ST_IconSetType" use="optional" default="3Arrows"/> + <xsd:attribute name="iconId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_SortBy"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="value"/> + <xsd:enumeration value="cellColor"/> + <xsd:enumeration value="fontColor"/> + <xsd:enumeration value="icon"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_SortMethod"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="stroke"/> + <xsd:enumeration value="pinYin"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DateGroupItem"> + <xsd:attribute name="year" type="xsd:unsignedShort" use="required"/> + <xsd:attribute name="month" type="xsd:unsignedShort" use="optional"/> + <xsd:attribute name="day" type="xsd:unsignedShort" use="optional"/> + <xsd:attribute name="hour" type="xsd:unsignedShort" use="optional"/> + <xsd:attribute name="minute" type="xsd:unsignedShort" use="optional"/> + <xsd:attribute name="second" type="xsd:unsignedShort" use="optional"/> + <xsd:attribute name="dateTimeGrouping" type="ST_DateTimeGrouping" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DateTimeGrouping"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="year"/> + <xsd:enumeration value="month"/> + <xsd:enumeration value="day"/> + <xsd:enumeration value="hour"/> + <xsd:enumeration value="minute"/> + <xsd:enumeration value="second"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CellRef"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Ref"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_RefA"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Sqref"> + <xsd:list itemType="ST_Ref"/> + </xsd:simpleType> + <xsd:simpleType name="ST_Formula"> + <xsd:restriction base="s:ST_Xstring"/> + </xsd:simpleType> + <xsd:simpleType name="ST_UnsignedIntHex"> + <xsd:restriction base="xsd:hexBinary"> + <xsd:length value="4"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_UnsignedShortHex"> + <xsd:restriction base="xsd:hexBinary"> + <xsd:length value="2"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_XStringElement"> + <xsd:attribute name="v" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <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_ObjectAnchor"> + <xsd:sequence> + <xsd:element ref="xdr:from" minOccurs="1" maxOccurs="1"/> + <xsd:element ref="xdr:to" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="moveWithCells" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="sizeWithCells" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:group name="EG_ExtensionList"> + <xsd:sequence> + <xsd:element name="ext" type="CT_Extension" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_ExtensionList"> + <xsd:sequence> + <xsd:group ref="EG_ExtensionList" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="calcChain" type="CT_CalcChain"/> + <xsd:complexType name="CT_CalcChain"> + <xsd:sequence> + <xsd:element name="c" type="CT_CalcCell" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CalcCell"> + <xsd:attribute name="r" type="ST_CellRef" use="optional"/> + <xsd:attribute name="ref" type="ST_CellRef" use="optional"/> + <xsd:attribute name="i" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="s" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="l" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="t" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="a" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:element name="comments" type="CT_Comments"/> + <xsd:complexType name="CT_Comments"> + <xsd:sequence> + <xsd:element name="authors" type="CT_Authors" minOccurs="1" maxOccurs="1"/> + <xsd:element name="commentList" type="CT_CommentList" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Authors"> + <xsd:sequence> + <xsd:element name="author" type="s:ST_Xstring" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CommentList"> + <xsd:sequence> + <xsd:element name="comment" type="CT_Comment" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Comment"> + <xsd:sequence> + <xsd:element name="text" type="CT_Rst" minOccurs="1" maxOccurs="1"/> + <xsd:element name="commentPr" type="CT_CommentPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute name="authorId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="guid" type="s:ST_Guid" use="optional"/> + <xsd:attribute name="shapeId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CommentPr"> + <xsd:sequence> + <xsd:element name="anchor" type="CT_ObjectAnchor" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="locked" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="defaultSize" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="print" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="disabled" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoFill" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoLine" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="altText" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="textHAlign" type="ST_TextHAlign" use="optional" default="left"/> + <xsd:attribute name="textVAlign" type="ST_TextVAlign" use="optional" default="top"/> + <xsd:attribute name="lockText" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="justLastX" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoScale" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextHAlign"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="left"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="right"/> + <xsd:enumeration value="justify"/> + <xsd:enumeration value="distributed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextVAlign"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="top"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="bottom"/> + <xsd:enumeration value="justify"/> + <xsd:enumeration value="distributed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="MapInfo" type="CT_MapInfo"/> + <xsd:complexType name="CT_MapInfo"> + <xsd:sequence> + <xsd:element name="Schema" type="CT_Schema" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="Map" type="CT_Map" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="SelectionNamespaces" type="xsd:string" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Schema" mixed="true"> + <xsd:sequence> + <xsd:any/> + </xsd:sequence> + <xsd:attribute name="ID" type="xsd:string" use="required"/> + <xsd:attribute name="SchemaRef" type="xsd:string" use="optional"/> + <xsd:attribute name="Namespace" type="xsd:string" use="optional"/> + <xsd:attribute name="SchemaLanguage" type="xsd:token" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Map"> + <xsd:sequence> + <xsd:element name="DataBinding" type="CT_DataBinding" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ID" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="Name" type="xsd:string" use="required"/> + <xsd:attribute name="RootElement" type="xsd:string" use="required"/> + <xsd:attribute name="SchemaID" type="xsd:string" use="required"/> + <xsd:attribute name="ShowImportExportValidationErrors" type="xsd:boolean" use="required"/> + <xsd:attribute name="AutoFit" type="xsd:boolean" use="required"/> + <xsd:attribute name="Append" type="xsd:boolean" use="required"/> + <xsd:attribute name="PreserveSortAFLayout" type="xsd:boolean" use="required"/> + <xsd:attribute name="PreserveFormat" type="xsd:boolean" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DataBinding"> + <xsd:sequence> + <xsd:any/> + </xsd:sequence> + <xsd:attribute name="DataBindingName" type="xsd:string" use="optional"/> + <xsd:attribute name="FileBinding" type="xsd:boolean" use="optional"/> + <xsd:attribute name="ConnectionID" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="FileBindingName" type="xsd:string" use="optional"/> + <xsd:attribute name="DataBindingLoadMode" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:element name="connections" type="CT_Connections"/> + <xsd:complexType name="CT_Connections"> + <xsd:sequence> + <xsd:element name="connection" minOccurs="1" maxOccurs="unbounded" type="CT_Connection"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Connection"> + <xsd:sequence> + <xsd:element name="dbPr" minOccurs="0" maxOccurs="1" type="CT_DbPr"/> + <xsd:element name="olapPr" minOccurs="0" maxOccurs="1" type="CT_OlapPr"/> + <xsd:element name="webPr" minOccurs="0" maxOccurs="1" type="CT_WebPr"/> + <xsd:element name="textPr" minOccurs="0" maxOccurs="1" type="CT_TextPr"/> + <xsd:element name="parameters" minOccurs="0" maxOccurs="1" type="CT_Parameters"/> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="id" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="sourceFile" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="odcFile" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="keepAlive" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="interval" use="optional" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="name" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="description" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="type" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="reconnectionMethod" use="optional" type="xsd:unsignedInt" default="1"/> + <xsd:attribute name="refreshedVersion" use="required" type="xsd:unsignedByte"/> + <xsd:attribute name="minRefreshableVersion" use="optional" type="xsd:unsignedByte" default="0"/> + <xsd:attribute name="savePassword" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="new" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="deleted" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="onlyUseConnectionFile" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="background" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="refreshOnLoad" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="saveData" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="credentials" use="optional" type="ST_CredMethod" default="integrated"/> + <xsd:attribute name="singleSignOnId" use="optional" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:simpleType name="ST_CredMethod"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="integrated"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="stored"/> + <xsd:enumeration value="prompt"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DbPr"> + <xsd:attribute name="connection" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="command" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="serverCommand" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="commandType" use="optional" type="xsd:unsignedInt" default="2"/> + </xsd:complexType> + <xsd:complexType name="CT_OlapPr"> + <xsd:attribute name="local" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="localConnection" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="localRefresh" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="sendLocale" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="rowDrillCount" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="serverFill" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="serverNumberFormat" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="serverFont" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="serverFontColor" use="optional" type="xsd:boolean" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_WebPr"> + <xsd:sequence> + <xsd:element name="tables" minOccurs="0" maxOccurs="1" type="CT_Tables"/> + </xsd:sequence> + <xsd:attribute name="xml" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="sourceData" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="parsePre" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="consecutive" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="firstRow" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="xl97" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="textDates" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="xl2000" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="url" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="post" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="htmlTables" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="htmlFormat" use="optional" type="ST_HtmlFmt" default="none"/> + <xsd:attribute name="editPage" use="optional" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:simpleType name="ST_HtmlFmt"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="rtf"/> + <xsd:enumeration value="all"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Parameters"> + <xsd:sequence> + <xsd:element name="parameter" minOccurs="1" maxOccurs="unbounded" type="CT_Parameter"/> + </xsd:sequence> + <xsd:attribute name="count" use="optional" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Parameter"> + <xsd:attribute name="name" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="sqlType" use="optional" type="xsd:int" default="0"/> + <xsd:attribute name="parameterType" use="optional" type="ST_ParameterType" default="prompt"/> + <xsd:attribute name="refreshOnChange" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="prompt" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="boolean" use="optional" type="xsd:boolean"/> + <xsd:attribute name="double" use="optional" type="xsd:double"/> + <xsd:attribute name="integer" use="optional" type="xsd:int"/> + <xsd:attribute name="string" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="cell" use="optional" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:simpleType name="ST_ParameterType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="prompt"/> + <xsd:enumeration value="value"/> + <xsd:enumeration value="cell"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Tables"> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="m" type="CT_TableMissing"/> + <xsd:element name="s" type="CT_XStringElement"/> + <xsd:element name="x" type="CT_Index"/> + </xsd:choice> + <xsd:attribute name="count" use="optional" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_TableMissing"/> + <xsd:complexType name="CT_TextPr"> + <xsd:sequence> + <xsd:element name="textFields" minOccurs="0" maxOccurs="1" type="CT_TextFields"/> + </xsd:sequence> + <xsd:attribute name="prompt" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="fileType" use="optional" type="ST_FileType" default="win"/> + <xsd:attribute name="codePage" use="optional" type="xsd:unsignedInt" default="1252"/> + <xsd:attribute name="characterSet" use="optional" type="xsd:string"/> + <xsd:attribute name="firstRow" use="optional" type="xsd:unsignedInt" default="1"/> + <xsd:attribute name="sourceFile" use="optional" type="s:ST_Xstring" default=""/> + <xsd:attribute name="delimited" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="decimal" use="optional" type="s:ST_Xstring" default="."/> + <xsd:attribute name="thousands" use="optional" type="s:ST_Xstring" default=","/> + <xsd:attribute name="tab" use="optional" type="xsd:boolean" default="true"/> + <xsd:attribute name="space" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="comma" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="semicolon" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="consecutive" use="optional" type="xsd:boolean" default="false"/> + <xsd:attribute name="qualifier" use="optional" type="ST_Qualifier" default="doubleQuote"/> + <xsd:attribute name="delimiter" use="optional" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:simpleType name="ST_FileType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="mac"/> + <xsd:enumeration value="win"/> + <xsd:enumeration value="dos"/> + <xsd:enumeration value="lin"/> + <xsd:enumeration value="other"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Qualifier"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="doubleQuote"/> + <xsd:enumeration value="singleQuote"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextFields"> + <xsd:sequence> + <xsd:element name="textField" minOccurs="1" maxOccurs="unbounded" type="CT_TextField"/> + </xsd:sequence> + <xsd:attribute name="count" use="optional" type="xsd:unsignedInt" default="1"/> + </xsd:complexType> + <xsd:complexType name="CT_TextField"> + <xsd:attribute name="type" use="optional" type="ST_ExternalConnectionType" default="general"/> + <xsd:attribute name="position" use="optional" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_ExternalConnectionType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="general"/> + <xsd:enumeration value="text"/> + <xsd:enumeration value="MDY"/> + <xsd:enumeration value="DMY"/> + <xsd:enumeration value="YMD"/> + <xsd:enumeration value="MYD"/> + <xsd:enumeration value="DYM"/> + <xsd:enumeration value="YDM"/> + <xsd:enumeration value="skip"/> + <xsd:enumeration value="EMD"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="pivotCacheDefinition" type="CT_PivotCacheDefinition"/> + <xsd:element name="pivotCacheRecords" type="CT_PivotCacheRecords"/> + <xsd:element name="pivotTableDefinition" type="CT_pivotTableDefinition"/> + <xsd:complexType name="CT_PivotCacheDefinition"> + <xsd:sequence> + <xsd:element name="cacheSource" type="CT_CacheSource" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cacheFields" type="CT_CacheFields" minOccurs="1" maxOccurs="1"/> + <xsd:element name="cacheHierarchies" minOccurs="0" type="CT_CacheHierarchies"/> + <xsd:element name="kpis" minOccurs="0" type="CT_PCDKPIs"/> + <xsd:element name="tupleCache" minOccurs="0" type="CT_TupleCache"/> + <xsd:element name="calculatedItems" minOccurs="0" type="CT_CalculatedItems"/> + <xsd:element name="calculatedMembers" type="CT_CalculatedMembers" minOccurs="0"/> + <xsd:element name="dimensions" type="CT_Dimensions" minOccurs="0"/> + <xsd:element name="measureGroups" type="CT_MeasureGroups" minOccurs="0"/> + <xsd:element name="maps" type="CT_MeasureDimensionMaps" minOccurs="0"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="optional"/> + <xsd:attribute name="invalid" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="saveData" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="refreshOnLoad" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="optimizeMemory" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="enableRefresh" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="refreshedBy" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="refreshedDate" type="xsd:double" use="optional"/> + <xsd:attribute name="refreshedDateIso" type="xsd:dateTime" use="optional"/> + <xsd:attribute name="backgroundQuery" type="xsd:boolean" default="false"/> + <xsd:attribute name="missingItemsLimit" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="createdVersion" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="refreshedVersion" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="minRefreshableVersion" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="recordCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="upgradeOnRefresh" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="tupleCache" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="supportSubquery" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="supportAdvancedDrill" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CacheFields"> + <xsd:sequence> + <xsd:element name="cacheField" type="CT_CacheField" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_CacheField"> + <xsd:sequence> + <xsd:element name="sharedItems" type="CT_SharedItems" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fieldGroup" minOccurs="0" type="CT_FieldGroup"/> + <xsd:element name="mpMap" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="caption" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="propertyName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="serverField" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="uniqueList" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + <xsd:attribute name="formula" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sqlType" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="hierarchy" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="level" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="databaseField" type="xsd:boolean" default="true"/> + <xsd:attribute name="mappingCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="memberPropertyField" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CacheSource"> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="worksheetSource" type="CT_WorksheetSource" minOccurs="1" maxOccurs="1"/> + <xsd:element name="consolidation" type="CT_Consolidation" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/> + </xsd:choice> + <xsd:attribute name="type" type="ST_SourceType" use="required"/> + <xsd:attribute name="connectionId" type="xsd:unsignedInt" default="0" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_SourceType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="worksheet"/> + <xsd:enumeration value="external"/> + <xsd:enumeration value="consolidation"/> + <xsd:enumeration value="scenario"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_WorksheetSource"> + <xsd:attribute name="ref" type="ST_Ref" use="optional"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sheet" type="s:ST_Xstring" use="optional"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Consolidation"> + <xsd:sequence> + <xsd:element name="pages" type="CT_Pages" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rangeSets" type="CT_RangeSets" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="autoPage" type="xsd:boolean" default="true" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Pages"> + <xsd:sequence> + <xsd:element name="page" type="CT_PCDSCPage" minOccurs="1" maxOccurs="4"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PCDSCPage"> + <xsd:sequence> + <xsd:element name="pageItem" type="CT_PageItem" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PageItem"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RangeSets"> + <xsd:sequence> + <xsd:element name="rangeSet" type="CT_RangeSet" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RangeSet"> + <xsd:attribute name="i1" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="i2" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="i3" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="i4" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="ref" type="ST_Ref" use="optional"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sheet" type="s:ST_Xstring" use="optional"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SharedItems"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="m" type="CT_Missing" minOccurs="1" maxOccurs="1"/> + <xsd:element name="n" type="CT_Number" minOccurs="1" maxOccurs="1"/> + <xsd:element name="b" type="CT_Boolean" minOccurs="1" maxOccurs="1"/> + <xsd:element name="e" type="CT_Error" minOccurs="1" maxOccurs="1"/> + <xsd:element name="s" type="CT_String" minOccurs="1" maxOccurs="1"/> + <xsd:element name="d" type="CT_DateTime" minOccurs="1" maxOccurs="1"/> + </xsd:choice> + <xsd:attribute name="containsSemiMixedTypes" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="containsNonDate" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="containsDate" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="containsString" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="containsBlank" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="containsMixedTypes" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="containsNumber" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="containsInteger" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="minValue" type="xsd:double" use="optional"/> + <xsd:attribute name="maxValue" type="xsd:double" use="optional"/> + <xsd:attribute name="minDate" type="xsd:dateTime" use="optional"/> + <xsd:attribute name="maxDate" type="xsd:dateTime" use="optional"/> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="longText" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Missing"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" maxOccurs="unbounded" type="CT_Tuples"/> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + <xsd:attribute name="in" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="fc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="un" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="st" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Number"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" maxOccurs="unbounded" type="CT_Tuples"/> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="v" use="required" type="xsd:double"/> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + <xsd:attribute name="in" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="fc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="un" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="st" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Boolean"> + <xsd:sequence> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="v" use="required" type="xsd:boolean"/> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Error"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" type="CT_Tuples"/> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="v" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + <xsd:attribute name="in" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="fc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="un" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="st" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_String"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" maxOccurs="unbounded" type="CT_Tuples"/> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="v" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + <xsd:attribute name="in" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="fc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="un" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="st" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_DateTime"> + <xsd:sequence> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="v" use="required" type="xsd:dateTime"/> + <xsd:attribute name="u" type="xsd:boolean"/> + <xsd:attribute name="f" type="xsd:boolean"/> + <xsd:attribute name="c" type="s:ST_Xstring"/> + <xsd:attribute name="cp" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_FieldGroup"> + <xsd:sequence> + <xsd:element name="rangePr" minOccurs="0" type="CT_RangePr"/> + <xsd:element name="discretePr" minOccurs="0" type="CT_DiscretePr"/> + <xsd:element name="groupItems" minOccurs="0" type="CT_GroupItems"/> + </xsd:sequence> + <xsd:attribute name="par" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="base" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RangePr"> + <xsd:attribute name="autoStart" type="xsd:boolean" default="true"/> + <xsd:attribute name="autoEnd" type="xsd:boolean" default="true"/> + <xsd:attribute name="groupBy" type="ST_GroupBy" default="range"/> + <xsd:attribute name="startNum" type="xsd:double"/> + <xsd:attribute name="endNum" type="xsd:double"/> + <xsd:attribute name="startDate" type="xsd:dateTime"/> + <xsd:attribute name="endDate" type="xsd:dateTime"/> + <xsd:attribute name="groupInterval" type="xsd:double" default="1"/> + </xsd:complexType> + <xsd:simpleType name="ST_GroupBy"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="range"/> + <xsd:enumeration value="seconds"/> + <xsd:enumeration value="minutes"/> + <xsd:enumeration value="hours"/> + <xsd:enumeration value="days"/> + <xsd:enumeration value="months"/> + <xsd:enumeration value="quarters"/> + <xsd:enumeration value="years"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DiscretePr"> + <xsd:sequence> + <xsd:element name="x" maxOccurs="unbounded" type="CT_Index"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupItems"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="m" type="CT_Missing"/> + <xsd:element name="n" type="CT_Number"/> + <xsd:element name="b" type="CT_Boolean"/> + <xsd:element name="e" type="CT_Error"/> + <xsd:element name="s" type="CT_String"/> + <xsd:element name="d" type="CT_DateTime"/> + </xsd:choice> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotCacheRecords"> + <xsd:sequence> + <xsd:element name="r" minOccurs="0" maxOccurs="unbounded" type="CT_Record"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Record"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="m" type="CT_Missing"/> + <xsd:element name="n" type="CT_Number"/> + <xsd:element name="b" type="CT_Boolean"/> + <xsd:element name="e" type="CT_Error"/> + <xsd:element name="s" type="CT_String"/> + <xsd:element name="d" type="CT_DateTime"/> + <xsd:element name="x" type="CT_Index"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_PCDKPIs"> + <xsd:sequence> + <xsd:element name="kpi" minOccurs="0" maxOccurs="unbounded" type="CT_PCDKPI"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PCDKPI"> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="displayFolder" type="s:ST_Xstring"/> + <xsd:attribute name="measureGroup" type="s:ST_Xstring"/> + <xsd:attribute name="parent" type="s:ST_Xstring"/> + <xsd:attribute name="value" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="goal" type="s:ST_Xstring"/> + <xsd:attribute name="status" type="s:ST_Xstring"/> + <xsd:attribute name="trend" type="s:ST_Xstring"/> + <xsd:attribute name="weight" type="s:ST_Xstring"/> + <xsd:attribute name="time" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_CacheHierarchies"> + <xsd:sequence> + <xsd:element name="cacheHierarchy" minOccurs="0" maxOccurs="unbounded" + type="CT_CacheHierarchy"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_CacheHierarchy"> + <xsd:sequence> + <xsd:element name="fieldsUsage" minOccurs="0" type="CT_FieldsUsage"/> + <xsd:element name="groupLevels" minOccurs="0" type="CT_GroupLevels"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="measure" type="xsd:boolean" default="false"/> + <xsd:attribute name="set" type="xsd:boolean" default="false"/> + <xsd:attribute name="parentSet" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="iconSet" type="xsd:int" default="0"/> + <xsd:attribute name="attribute" type="xsd:boolean" default="false"/> + <xsd:attribute name="time" type="xsd:boolean" default="false"/> + <xsd:attribute name="keyAttribute" type="xsd:boolean" default="false"/> + <xsd:attribute name="defaultMemberUniqueName" type="s:ST_Xstring"/> + <xsd:attribute name="allUniqueName" type="s:ST_Xstring"/> + <xsd:attribute name="allCaption" type="s:ST_Xstring"/> + <xsd:attribute name="dimensionUniqueName" type="s:ST_Xstring"/> + <xsd:attribute name="displayFolder" type="s:ST_Xstring"/> + <xsd:attribute name="measureGroup" type="s:ST_Xstring"/> + <xsd:attribute name="measures" type="xsd:boolean" default="false"/> + <xsd:attribute name="count" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="oneField" type="xsd:boolean" default="false"/> + <xsd:attribute name="memberValueDatatype" use="optional" type="xsd:unsignedShort"/> + <xsd:attribute name="unbalanced" use="optional" type="xsd:boolean"/> + <xsd:attribute name="unbalancedGroup" use="optional" type="xsd:boolean"/> + <xsd:attribute name="hidden" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_FieldsUsage"> + <xsd:sequence> + <xsd:element name="fieldUsage" minOccurs="0" maxOccurs="unbounded" type="CT_FieldUsage"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_FieldUsage"> + <xsd:attribute name="x" use="required" type="xsd:int"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupLevels"> + <xsd:sequence> + <xsd:element name="groupLevel" maxOccurs="unbounded" type="CT_GroupLevel"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupLevel"> + <xsd:sequence> + <xsd:element name="groups" minOccurs="0" type="CT_Groups"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="user" type="xsd:boolean" default="false"/> + <xsd:attribute name="customRollUp" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Groups"> + <xsd:sequence> + <xsd:element name="group" maxOccurs="unbounded" type="CT_LevelGroup"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_LevelGroup"> + <xsd:sequence> + <xsd:element name="groupMembers" type="CT_GroupMembers"/> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="uniqueParent" type="s:ST_Xstring"/> + <xsd:attribute name="id" type="xsd:int"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupMembers"> + <xsd:sequence> + <xsd:element name="groupMember" maxOccurs="unbounded" type="CT_GroupMember"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_GroupMember"> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="group" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_TupleCache"> + <xsd:sequence> + <xsd:element name="entries" minOccurs="0" type="CT_PCDSDTCEntries"/> + <xsd:element name="sets" minOccurs="0" type="CT_Sets"/> + <xsd:element name="queryCache" minOccurs="0" type="CT_QueryCache"/> + <xsd:element name="serverFormats" minOccurs="0" maxOccurs="1" type="CT_ServerFormats"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ServerFormat"> + <xsd:attribute name="culture" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="format" use="optional" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_ServerFormats"> + <xsd:sequence> + <xsd:element name="serverFormat" type="CT_ServerFormat" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PCDSDTCEntries"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="m" type="CT_Missing"/> + <xsd:element name="n" type="CT_Number"/> + <xsd:element name="e" type="CT_Error"/> + <xsd:element name="s" type="CT_String"/> + </xsd:choice> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Tuples"> + <xsd:sequence> + <xsd:element name="tpl" type="CT_Tuple" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="c" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Tuple"> + <xsd:attribute name="fld" type="xsd:unsignedInt"/> + <xsd:attribute name="hier" type="xsd:unsignedInt"/> + <xsd:attribute name="item" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Sets"> + <xsd:sequence> + <xsd:element name="set" maxOccurs="unbounded" type="CT_Set"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Set"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" maxOccurs="unbounded" type="CT_Tuples"/> + <xsd:element name="sortByTuple" minOccurs="0" type="CT_Tuples"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + <xsd:attribute name="maxRank" use="required" type="xsd:int"/> + <xsd:attribute name="setDefinition" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="sortType" type="ST_SortType" default="none"/> + <xsd:attribute name="queryFailed" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_SortType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="ascending"/> + <xsd:enumeration value="descending"/> + <xsd:enumeration value="ascendingAlpha"/> + <xsd:enumeration value="descendingAlpha"/> + <xsd:enumeration value="ascendingNatural"/> + <xsd:enumeration value="descendingNatural"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_QueryCache"> + <xsd:sequence> + <xsd:element name="query" maxOccurs="unbounded" type="CT_Query"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Query"> + <xsd:sequence> + <xsd:element name="tpls" minOccurs="0" type="CT_Tuples"/> + </xsd:sequence> + <xsd:attribute name="mdx" use="required" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_CalculatedItems"> + <xsd:sequence> + <xsd:element name="calculatedItem" maxOccurs="unbounded" type="CT_CalculatedItem"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_CalculatedItem"> + <xsd:sequence> + <xsd:element name="pivotArea" type="CT_PivotArea"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="field" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="formula" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_CalculatedMembers"> + <xsd:sequence> + <xsd:element name="calculatedMember" maxOccurs="unbounded" type="CT_CalculatedMember"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_CalculatedMember"> + <xsd:sequence minOccurs="0"> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="mdx" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="memberName" type="s:ST_Xstring"/> + <xsd:attribute name="hierarchy" type="s:ST_Xstring"/> + <xsd:attribute name="parent" type="s:ST_Xstring"/> + <xsd:attribute name="solveOrder" type="xsd:int" default="0"/> + <xsd:attribute name="set" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_pivotTableDefinition"> + <xsd:sequence> + <xsd:element name="location" type="CT_Location"/> + <xsd:element name="pivotFields" type="CT_PivotFields" minOccurs="0"/> + <xsd:element name="rowFields" type="CT_RowFields" minOccurs="0"/> + <xsd:element name="rowItems" type="CT_rowItems" minOccurs="0"/> + <xsd:element name="colFields" type="CT_ColFields" minOccurs="0"/> + <xsd:element name="colItems" type="CT_colItems" minOccurs="0"/> + <xsd:element name="pageFields" type="CT_PageFields" minOccurs="0"/> + <xsd:element name="dataFields" type="CT_DataFields" minOccurs="0"/> + <xsd:element name="formats" type="CT_Formats" minOccurs="0"/> + <xsd:element name="conditionalFormats" type="CT_ConditionalFormats" minOccurs="0"/> + <xsd:element name="chartFormats" type="CT_ChartFormats" minOccurs="0"/> + <xsd:element name="pivotHierarchies" type="CT_PivotHierarchies" minOccurs="0"/> + <xsd:element name="pivotTableStyleInfo" minOccurs="0" maxOccurs="1" type="CT_PivotTableStyle"/> + <xsd:element name="filters" minOccurs="0" maxOccurs="1" type="CT_PivotFilters"/> + <xsd:element name="rowHierarchiesUsage" type="CT_RowHierarchiesUsage" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="colHierarchiesUsage" type="CT_ColHierarchiesUsage" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="cacheId" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="dataOnRows" type="xsd:boolean" default="false"/> + <xsd:attribute name="dataPosition" type="xsd:unsignedInt" use="optional"/> + <xsd:attributeGroup ref="AG_AutoFormat"/> + <xsd:attribute name="dataCaption" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="grandTotalCaption" type="s:ST_Xstring"/> + <xsd:attribute name="errorCaption" type="s:ST_Xstring"/> + <xsd:attribute name="showError" type="xsd:boolean" default="false"/> + <xsd:attribute name="missingCaption" type="s:ST_Xstring"/> + <xsd:attribute name="showMissing" type="xsd:boolean" default="true"/> + <xsd:attribute name="pageStyle" type="s:ST_Xstring"/> + <xsd:attribute name="pivotTableStyle" type="s:ST_Xstring"/> + <xsd:attribute name="vacatedStyle" type="s:ST_Xstring"/> + <xsd:attribute name="tag" type="s:ST_Xstring"/> + <xsd:attribute name="updatedVersion" type="xsd:unsignedByte" default="0"/> + <xsd:attribute name="minRefreshableVersion" type="xsd:unsignedByte" default="0"/> + <xsd:attribute name="asteriskTotals" type="xsd:boolean" default="false"/> + <xsd:attribute name="showItems" type="xsd:boolean" default="true"/> + <xsd:attribute name="editData" type="xsd:boolean" default="false"/> + <xsd:attribute name="disableFieldList" type="xsd:boolean" default="false"/> + <xsd:attribute name="showCalcMbrs" type="xsd:boolean" default="true"/> + <xsd:attribute name="visualTotals" type="xsd:boolean" default="true"/> + <xsd:attribute name="showMultipleLabel" type="xsd:boolean" default="true"/> + <xsd:attribute name="showDataDropDown" type="xsd:boolean" default="true"/> + <xsd:attribute name="showDrill" type="xsd:boolean" default="true"/> + <xsd:attribute name="printDrill" type="xsd:boolean" default="false"/> + <xsd:attribute name="showMemberPropertyTips" type="xsd:boolean" default="true"/> + <xsd:attribute name="showDataTips" type="xsd:boolean" default="true"/> + <xsd:attribute name="enableWizard" type="xsd:boolean" default="true"/> + <xsd:attribute name="enableDrill" type="xsd:boolean" default="true"/> + <xsd:attribute name="enableFieldProperties" type="xsd:boolean" default="true"/> + <xsd:attribute name="preserveFormatting" type="xsd:boolean" default="true"/> + <xsd:attribute name="useAutoFormatting" type="xsd:boolean" default="false"/> + <xsd:attribute name="pageWrap" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="pageOverThenDown" type="xsd:boolean" default="false"/> + <xsd:attribute name="subtotalHiddenItems" type="xsd:boolean" default="false"/> + <xsd:attribute name="rowGrandTotals" type="xsd:boolean" default="true"/> + <xsd:attribute name="colGrandTotals" type="xsd:boolean" default="true"/> + <xsd:attribute name="fieldPrintTitles" type="xsd:boolean" default="false"/> + <xsd:attribute name="itemPrintTitles" type="xsd:boolean" default="false"/> + <xsd:attribute name="mergeItem" type="xsd:boolean" default="false"/> + <xsd:attribute name="showDropZones" type="xsd:boolean" default="true"/> + <xsd:attribute name="createdVersion" type="xsd:unsignedByte" default="0"/> + <xsd:attribute name="indent" type="xsd:unsignedInt" default="1"/> + <xsd:attribute name="showEmptyRow" type="xsd:boolean" default="false"/> + <xsd:attribute name="showEmptyCol" type="xsd:boolean" default="false"/> + <xsd:attribute name="showHeaders" type="xsd:boolean" default="true"/> + <xsd:attribute name="compact" type="xsd:boolean" default="true"/> + <xsd:attribute name="outline" type="xsd:boolean" default="false"/> + <xsd:attribute name="outlineData" type="xsd:boolean" default="false"/> + <xsd:attribute name="compactData" type="xsd:boolean" default="true"/> + <xsd:attribute name="published" type="xsd:boolean" default="false"/> + <xsd:attribute name="gridDropZones" type="xsd:boolean" default="false"/> + <xsd:attribute name="immersive" type="xsd:boolean" default="true"/> + <xsd:attribute name="multipleFieldFilters" type="xsd:boolean" default="true"/> + <xsd:attribute name="chartFormat" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="rowHeaderCaption" type="s:ST_Xstring"/> + <xsd:attribute name="colHeaderCaption" type="s:ST_Xstring"/> + <xsd:attribute name="fieldListSortAscending" type="xsd:boolean" default="false"/> + <xsd:attribute name="mdxSubqueries" type="xsd:boolean" default="false"/> + <xsd:attribute name="customListSort" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_Location"> + <xsd:attribute name="ref" use="required" type="ST_Ref"/> + <xsd:attribute name="firstHeaderRow" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="firstDataRow" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="firstDataCol" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="rowPageCount" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="colPageCount" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotFields"> + <xsd:sequence> + <xsd:element name="pivotField" maxOccurs="unbounded" type="CT_PivotField"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotField"> + <xsd:sequence> + <xsd:element name="items" minOccurs="0" type="CT_Items"/> + <xsd:element name="autoSortScope" minOccurs="0" type="CT_AutoSortScope"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring"/> + <xsd:attribute name="axis" use="optional" type="ST_Axis"/> + <xsd:attribute name="dataField" type="xsd:boolean" default="false"/> + <xsd:attribute name="subtotalCaption" type="s:ST_Xstring"/> + <xsd:attribute name="showDropDowns" type="xsd:boolean" default="true"/> + <xsd:attribute name="hiddenLevel" type="xsd:boolean" default="false"/> + <xsd:attribute name="uniqueMemberProperty" type="s:ST_Xstring"/> + <xsd:attribute name="compact" type="xsd:boolean" default="true"/> + <xsd:attribute name="allDrilled" type="xsd:boolean" default="false"/> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + <xsd:attribute name="outline" type="xsd:boolean" default="true"/> + <xsd:attribute name="subtotalTop" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToRow" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToCol" type="xsd:boolean" default="true"/> + <xsd:attribute name="multipleItemSelectionAllowed" type="xsd:boolean" default="false"/> + <xsd:attribute name="dragToPage" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToData" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragOff" type="xsd:boolean" default="true"/> + <xsd:attribute name="showAll" type="xsd:boolean" default="true"/> + <xsd:attribute name="insertBlankRow" type="xsd:boolean" default="false"/> + <xsd:attribute name="serverField" type="xsd:boolean" default="false"/> + <xsd:attribute name="insertPageBreak" type="xsd:boolean" default="false"/> + <xsd:attribute name="autoShow" type="xsd:boolean" default="false"/> + <xsd:attribute name="topAutoShow" type="xsd:boolean" default="true"/> + <xsd:attribute name="hideNewItems" type="xsd:boolean" default="false"/> + <xsd:attribute name="measureFilter" type="xsd:boolean" default="false"/> + <xsd:attribute name="includeNewItemsInFilter" type="xsd:boolean" default="false"/> + <xsd:attribute name="itemPageCount" type="xsd:unsignedInt" default="10"/> + <xsd:attribute name="sortType" type="ST_FieldSortType" default="manual"/> + <xsd:attribute name="dataSourceSort" type="xsd:boolean" use="optional"/> + <xsd:attribute name="nonAutoSortDefault" type="xsd:boolean" default="false"/> + <xsd:attribute name="rankBy" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="defaultSubtotal" type="xsd:boolean" default="true"/> + <xsd:attribute name="sumSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="countASubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="avgSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="maxSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="minSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="productSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="countSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="stdDevSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="stdDevPSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="varSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="varPSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="showPropCell" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showPropTip" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showPropAsCaption" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="defaultAttributeDrillState" type="xsd:boolean" use="optional" + default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_AutoSortScope"> + <xsd:sequence> + <xsd:element name="pivotArea" type="CT_PivotArea"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Items"> + <xsd:sequence> + <xsd:element name="item" maxOccurs="unbounded" type="CT_Item"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Item"> + <xsd:attribute name="n" type="s:ST_Xstring"/> + <xsd:attribute name="t" type="ST_ItemType" default="data"/> + <xsd:attribute name="h" type="xsd:boolean" default="false"/> + <xsd:attribute name="s" type="xsd:boolean" default="false"/> + <xsd:attribute name="sd" type="xsd:boolean" default="true"/> + <xsd:attribute name="f" type="xsd:boolean" default="false"/> + <xsd:attribute name="m" type="xsd:boolean" default="false"/> + <xsd:attribute name="c" type="xsd:boolean" default="false"/> + <xsd:attribute name="x" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="d" type="xsd:boolean" default="false"/> + <xsd:attribute name="e" type="xsd:boolean" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_PageFields"> + <xsd:sequence> + <xsd:element name="pageField" maxOccurs="unbounded" type="CT_PageField"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PageField"> + <xsd:sequence minOccurs="0"> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="fld" use="required" type="xsd:int"/> + <xsd:attribute name="item" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="hier" type="xsd:int"/> + <xsd:attribute name="name" type="s:ST_Xstring"/> + <xsd:attribute name="cap" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_DataFields"> + <xsd:sequence> + <xsd:element name="dataField" maxOccurs="unbounded" type="CT_DataField"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_DataField"> + <xsd:sequence> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" use="optional" type="s:ST_Xstring"/> + <xsd:attribute name="fld" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="subtotal" type="ST_DataConsolidateFunction" default="sum"/> + <xsd:attribute name="showDataAs" type="ST_ShowDataAs" default="normal"/> + <xsd:attribute name="baseField" type="xsd:int" default="-1"/> + <xsd:attribute name="baseItem" type="xsd:unsignedInt" default="1048832"/> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_rowItems"> + <xsd:sequence> + <xsd:element name="i" maxOccurs="unbounded" type="CT_I"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_colItems"> + <xsd:sequence> + <xsd:element name="i" maxOccurs="unbounded" type="CT_I"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_I"> + <xsd:sequence> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_X"/> + </xsd:sequence> + <xsd:attribute name="t" type="ST_ItemType" default="data"/> + <xsd:attribute name="r" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="i" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_X"> + <xsd:attribute name="v" type="xsd:int" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_RowFields"> + <xsd:sequence> + <xsd:element name="field" maxOccurs="unbounded" type="CT_Field"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_ColFields"> + <xsd:sequence> + <xsd:element name="field" maxOccurs="unbounded" type="CT_Field"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Field"> + <xsd:attribute name="x" type="xsd:int" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Formats"> + <xsd:sequence> + <xsd:element name="format" maxOccurs="unbounded" type="CT_Format"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Format"> + <xsd:sequence> + <xsd:element name="pivotArea" type="CT_PivotArea"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="action" type="ST_FormatAction" default="formatting"/> + <xsd:attribute name="dxfId" type="ST_DxfId" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ConditionalFormats"> + <xsd:sequence> + <xsd:element name="conditionalFormat" maxOccurs="unbounded" type="CT_ConditionalFormat"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_ConditionalFormat"> + <xsd:sequence> + <xsd:element name="pivotAreas" type="CT_PivotAreas"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="scope" type="ST_Scope" default="selection"/> + <xsd:attribute name="type" type="ST_Type" default="none"/> + <xsd:attribute name="priority" use="required" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotAreas"> + <xsd:sequence> + <xsd:element name="pivotArea" minOccurs="0" maxOccurs="unbounded" type="CT_PivotArea"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:simpleType name="ST_Scope"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="selection"/> + <xsd:enumeration value="data"/> + <xsd:enumeration value="field"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Type"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="all"/> + <xsd:enumeration value="row"/> + <xsd:enumeration value="column"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ChartFormats"> + <xsd:sequence> + <xsd:element name="chartFormat" maxOccurs="unbounded" type="CT_ChartFormat"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_ChartFormat"> + <xsd:sequence> + <xsd:element name="pivotArea" type="CT_PivotArea"/> + </xsd:sequence> + <xsd:attribute name="chart" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="format" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="series" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotHierarchies"> + <xsd:sequence> + <xsd:element name="pivotHierarchy" maxOccurs="unbounded" type="CT_PivotHierarchy"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotHierarchy"> + <xsd:sequence> + <xsd:element name="mps" minOccurs="0" type="CT_MemberProperties"/> + <xsd:element name="members" minOccurs="0" maxOccurs="unbounded" type="CT_Members"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="outline" type="xsd:boolean" default="false"/> + <xsd:attribute name="multipleItemSelectionAllowed" type="xsd:boolean" default="false"/> + <xsd:attribute name="subtotalTop" type="xsd:boolean" default="false"/> + <xsd:attribute name="showInFieldList" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToRow" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToCol" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToPage" type="xsd:boolean" default="true"/> + <xsd:attribute name="dragToData" type="xsd:boolean" default="false"/> + <xsd:attribute name="dragOff" type="xsd:boolean" default="true"/> + <xsd:attribute name="includeNewItemsInFilter" type="xsd:boolean" default="false"/> + <xsd:attribute name="caption" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RowHierarchiesUsage"> + <xsd:sequence> + <xsd:element name="rowHierarchyUsage" minOccurs="1" maxOccurs="unbounded" + type="CT_HierarchyUsage"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_ColHierarchiesUsage"> + <xsd:sequence> + <xsd:element name="colHierarchyUsage" minOccurs="1" maxOccurs="unbounded" + type="CT_HierarchyUsage"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_HierarchyUsage"> + <xsd:attribute name="hierarchyUsage" type="xsd:int" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_MemberProperties"> + <xsd:sequence> + <xsd:element name="mp" maxOccurs="unbounded" type="CT_MemberProperty"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_MemberProperty"> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="showCell" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showTip" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showAsCaption" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="nameLen" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="pPos" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="pLen" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="level" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="field" use="required" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Members"> + <xsd:sequence> + <xsd:element name="member" maxOccurs="unbounded" type="CT_Member"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + <xsd:attribute name="level" use="optional" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_Member"> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_Dimensions"> + <xsd:sequence> + <xsd:element name="dimension" minOccurs="0" maxOccurs="unbounded" type="CT_PivotDimension"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotDimension"> + <xsd:attribute name="measure" type="xsd:boolean" default="false"/> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="uniqueName" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="required" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_MeasureGroups"> + <xsd:sequence> + <xsd:element name="measureGroup" minOccurs="0" maxOccurs="unbounded" type="CT_MeasureGroup"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_MeasureDimensionMaps"> + <xsd:sequence> + <xsd:element name="map" minOccurs="0" maxOccurs="unbounded" type="CT_MeasureDimensionMap"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_MeasureGroup"> + <xsd:attribute name="name" use="required" type="s:ST_Xstring"/> + <xsd:attribute name="caption" use="required" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_MeasureDimensionMap"> + <xsd:attribute name="measureGroup" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="dimension" use="optional" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotTableStyle"> + <xsd:attribute name="name" type="xsd:string"/> + <xsd:attribute name="showRowHeaders" type="xsd:boolean"/> + <xsd:attribute name="showColHeaders" type="xsd:boolean"/> + <xsd:attribute name="showRowStripes" type="xsd:boolean"/> + <xsd:attribute name="showColStripes" type="xsd:boolean"/> + <xsd:attribute name="showLastColumn" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotFilters"> + <xsd:sequence> + <xsd:element name="filter" minOccurs="0" maxOccurs="unbounded" type="CT_PivotFilter"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotFilter"> + <xsd:sequence> + <xsd:element name="autoFilter" minOccurs="1" maxOccurs="1" type="CT_AutoFilter"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="fld" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="mpFld" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="type" use="required" type="ST_PivotFilterType"/> + <xsd:attribute name="evalOrder" use="optional" type="xsd:int" default="0"/> + <xsd:attribute name="id" use="required" type="xsd:unsignedInt"/> + <xsd:attribute name="iMeasureHier" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="iMeasureFld" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="name" type="s:ST_Xstring"/> + <xsd:attribute name="description" type="s:ST_Xstring"/> + <xsd:attribute name="stringValue1" type="s:ST_Xstring"/> + <xsd:attribute name="stringValue2" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:simpleType name="ST_ShowDataAs"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="difference"/> + <xsd:enumeration value="percent"/> + <xsd:enumeration value="percentDiff"/> + <xsd:enumeration value="runTotal"/> + <xsd:enumeration value="percentOfRow"/> + <xsd:enumeration value="percentOfCol"/> + <xsd:enumeration value="percentOfTotal"/> + <xsd:enumeration value="index"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ItemType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="data"/> + <xsd:enumeration value="default"/> + <xsd:enumeration value="sum"/> + <xsd:enumeration value="countA"/> + <xsd:enumeration value="avg"/> + <xsd:enumeration value="max"/> + <xsd:enumeration value="min"/> + <xsd:enumeration value="product"/> + <xsd:enumeration value="count"/> + <xsd:enumeration value="stdDev"/> + <xsd:enumeration value="stdDevP"/> + <xsd:enumeration value="var"/> + <xsd:enumeration value="varP"/> + <xsd:enumeration value="grand"/> + <xsd:enumeration value="blank"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FormatAction"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="blank"/> + <xsd:enumeration value="formatting"/> + <xsd:enumeration value="drill"/> + <xsd:enumeration value="formula"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FieldSortType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="manual"/> + <xsd:enumeration value="ascending"/> + <xsd:enumeration value="descending"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PivotFilterType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="unknown"/> + <xsd:enumeration value="count"/> + <xsd:enumeration value="percent"/> + <xsd:enumeration value="sum"/> + <xsd:enumeration value="captionEqual"/> + <xsd:enumeration value="captionNotEqual"/> + <xsd:enumeration value="captionBeginsWith"/> + <xsd:enumeration value="captionNotBeginsWith"/> + <xsd:enumeration value="captionEndsWith"/> + <xsd:enumeration value="captionNotEndsWith"/> + <xsd:enumeration value="captionContains"/> + <xsd:enumeration value="captionNotContains"/> + <xsd:enumeration value="captionGreaterThan"/> + <xsd:enumeration value="captionGreaterThanOrEqual"/> + <xsd:enumeration value="captionLessThan"/> + <xsd:enumeration value="captionLessThanOrEqual"/> + <xsd:enumeration value="captionBetween"/> + <xsd:enumeration value="captionNotBetween"/> + <xsd:enumeration value="valueEqual"/> + <xsd:enumeration value="valueNotEqual"/> + <xsd:enumeration value="valueGreaterThan"/> + <xsd:enumeration value="valueGreaterThanOrEqual"/> + <xsd:enumeration value="valueLessThan"/> + <xsd:enumeration value="valueLessThanOrEqual"/> + <xsd:enumeration value="valueBetween"/> + <xsd:enumeration value="valueNotBetween"/> + <xsd:enumeration value="dateEqual"/> + <xsd:enumeration value="dateNotEqual"/> + <xsd:enumeration value="dateOlderThan"/> + <xsd:enumeration value="dateOlderThanOrEqual"/> + <xsd:enumeration value="dateNewerThan"/> + <xsd:enumeration value="dateNewerThanOrEqual"/> + <xsd:enumeration value="dateBetween"/> + <xsd:enumeration value="dateNotBetween"/> + <xsd:enumeration value="tomorrow"/> + <xsd:enumeration value="today"/> + <xsd:enumeration value="yesterday"/> + <xsd:enumeration value="nextWeek"/> + <xsd:enumeration value="thisWeek"/> + <xsd:enumeration value="lastWeek"/> + <xsd:enumeration value="nextMonth"/> + <xsd:enumeration value="thisMonth"/> + <xsd:enumeration value="lastMonth"/> + <xsd:enumeration value="nextQuarter"/> + <xsd:enumeration value="thisQuarter"/> + <xsd:enumeration value="lastQuarter"/> + <xsd:enumeration value="nextYear"/> + <xsd:enumeration value="thisYear"/> + <xsd:enumeration value="lastYear"/> + <xsd:enumeration value="yearToDate"/> + <xsd:enumeration value="Q1"/> + <xsd:enumeration value="Q2"/> + <xsd:enumeration value="Q3"/> + <xsd:enumeration value="Q4"/> + <xsd:enumeration value="M1"/> + <xsd:enumeration value="M2"/> + <xsd:enumeration value="M3"/> + <xsd:enumeration value="M4"/> + <xsd:enumeration value="M5"/> + <xsd:enumeration value="M6"/> + <xsd:enumeration value="M7"/> + <xsd:enumeration value="M8"/> + <xsd:enumeration value="M9"/> + <xsd:enumeration value="M10"/> + <xsd:enumeration value="M11"/> + <xsd:enumeration value="M12"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PivotArea"> + <xsd:sequence> + <xsd:element name="references" minOccurs="0" type="CT_PivotAreaReferences"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="field" use="optional" type="xsd:int"/> + <xsd:attribute name="type" type="ST_PivotAreaType" default="normal"/> + <xsd:attribute name="dataOnly" type="xsd:boolean" default="true"/> + <xsd:attribute name="labelOnly" type="xsd:boolean" default="false"/> + <xsd:attribute name="grandRow" type="xsd:boolean" default="false"/> + <xsd:attribute name="grandCol" type="xsd:boolean" default="false"/> + <xsd:attribute name="cacheIndex" type="xsd:boolean" default="false"/> + <xsd:attribute name="outline" type="xsd:boolean" default="true"/> + <xsd:attribute name="offset" type="ST_Ref"/> + <xsd:attribute name="collapsedLevelsAreSubtotals" type="xsd:boolean" default="false"/> + <xsd:attribute name="axis" type="ST_Axis" use="optional"/> + <xsd:attribute name="fieldPosition" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PivotAreaType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="data"/> + <xsd:enumeration value="all"/> + <xsd:enumeration value="origin"/> + <xsd:enumeration value="button"/> + <xsd:enumeration value="topEnd"/> + <xsd:enumeration value="topRight"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PivotAreaReferences"> + <xsd:sequence> + <xsd:element name="reference" maxOccurs="unbounded" type="CT_PivotAreaReference"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotAreaReference"> + <xsd:sequence> + <xsd:element name="x" minOccurs="0" maxOccurs="unbounded" type="CT_Index"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="field" use="optional" type="xsd:unsignedInt"/> + <xsd:attribute name="count" type="xsd:unsignedInt"/> + <xsd:attribute name="selected" type="xsd:boolean" default="true"/> + <xsd:attribute name="byPosition" type="xsd:boolean" default="false"/> + <xsd:attribute name="relative" type="xsd:boolean" default="false"/> + <xsd:attribute name="defaultSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="sumSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="countASubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="avgSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="maxSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="minSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="productSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="countSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="stdDevSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="stdDevPSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="varSubtotal" type="xsd:boolean" default="false"/> + <xsd:attribute name="varPSubtotal" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Index"> + <xsd:attribute name="v" use="required" type="xsd:unsignedInt"/> + </xsd:complexType> + <xsd:simpleType name="ST_Axis"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="axisRow"/> + <xsd:enumeration value="axisCol"/> + <xsd:enumeration value="axisPage"/> + <xsd:enumeration value="axisValues"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="queryTable" type="CT_QueryTable"/> + <xsd:complexType name="CT_QueryTable"> + <xsd:sequence> + <xsd:element name="queryTableRefresh" type="CT_QueryTableRefresh" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="headers" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="rowNumbers" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="disableRefresh" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="backgroundRefresh" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="firstBackgroundRefresh" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="refreshOnLoad" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="growShrinkType" type="ST_GrowShrinkType" use="optional" + default="insertDelete"/> + <xsd:attribute name="fillFormulas" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="removeDataOnSave" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="disableEdit" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="preserveFormatting" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="adjustColumnWidth" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="intermediate" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="connectionId" type="xsd:unsignedInt" use="required"/> + <xsd:attributeGroup ref="AG_AutoFormat"/> + </xsd:complexType> + <xsd:complexType name="CT_QueryTableRefresh"> + <xsd:sequence> + <xsd:element name="queryTableFields" type="CT_QueryTableFields" minOccurs="1" maxOccurs="1"/> + <xsd:element name="queryTableDeletedFields" type="CT_QueryTableDeletedFields" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="sortState" minOccurs="0" maxOccurs="1" type="CT_SortState"/> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="preserveSortFilterLayout" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="fieldIdWrapped" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="headersInLastRefresh" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="minimumVersion" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="nextId" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="unboundColumnsLeft" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="unboundColumnsRight" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_QueryTableDeletedFields"> + <xsd:sequence> + <xsd:element name="deletedField" type="CT_DeletedField" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DeletedField"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_QueryTableFields"> + <xsd:sequence> + <xsd:element name="queryTableField" type="CT_QueryTableField" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_QueryTableField"> + <xsd:sequence minOccurs="0"> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="dataBound" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="rowNumbers" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="fillFormulas" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="clipped" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="tableColumnId" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:simpleType name="ST_GrowShrinkType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="insertDelete"/> + <xsd:enumeration value="insertClear"/> + <xsd:enumeration value="overwriteClear"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="sst" type="CT_Sst"/> + <xsd:complexType name="CT_Sst"> + <xsd:sequence> + <xsd:element name="si" type="CT_Rst" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="uniqueCount" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PhoneticType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="halfwidthKatakana"/> + <xsd:enumeration value="fullwidthKatakana"/> + <xsd:enumeration value="Hiragana"/> + <xsd:enumeration value="noConversion"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PhoneticAlignment"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="noControl"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="distributed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PhoneticRun"> + <xsd:sequence> + <xsd:element name="t" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="sb" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="eb" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RElt"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_RPrElt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="t" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_RPrElt"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="rFont" type="CT_FontName" minOccurs="0" maxOccurs="1"/> + <xsd:element name="charset" type="CT_IntProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="family" type="CT_IntProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="b" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="i" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="strike" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="outline" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shadow" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="condense" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extend" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="color" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sz" type="CT_FontSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="u" type="CT_UnderlineProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="vertAlign" type="CT_VerticalAlignFontProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scheme" type="CT_FontScheme" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_Rst"> + <xsd:sequence> + <xsd:element name="t" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="r" type="CT_RElt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rPh" type="CT_PhoneticRun" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="phoneticPr" minOccurs="0" maxOccurs="1" type="CT_PhoneticPr"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PhoneticPr"> + <xsd:attribute name="fontId" type="ST_FontId" use="required"/> + <xsd:attribute name="type" type="ST_PhoneticType" use="optional" default="fullwidthKatakana"/> + <xsd:attribute name="alignment" type="ST_PhoneticAlignment" use="optional" default="left"/> + </xsd:complexType> + <xsd:element name="headers" type="CT_RevisionHeaders"/> + <xsd:element name="revisions" type="CT_Revisions"/> + <xsd:complexType name="CT_RevisionHeaders"> + <xsd:sequence> + <xsd:element name="header" type="CT_RevisionHeader" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="lastGuid" type="s:ST_Guid" use="optional"/> + <xsd:attribute name="shared" type="xsd:boolean" default="true"/> + <xsd:attribute name="diskRevisions" type="xsd:boolean" default="false"/> + <xsd:attribute name="history" type="xsd:boolean" default="true"/> + <xsd:attribute name="trackRevisions" type="xsd:boolean" default="true"/> + <xsd:attribute name="exclusive" type="xsd:boolean" default="false"/> + <xsd:attribute name="revisionId" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="version" type="xsd:int" default="1"/> + <xsd:attribute name="keepChangeHistory" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="protected" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="preserveHistory" type="xsd:unsignedInt" default="30"/> + </xsd:complexType> + <xsd:complexType name="CT_Revisions"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="rrc" type="CT_RevisionRowColumn" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rm" type="CT_RevisionMove" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcv" type="CT_RevisionCustomView" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rsnm" type="CT_RevisionSheetRename" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="ris" type="CT_RevisionInsertSheet" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcc" type="CT_RevisionCellChange" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rfmt" type="CT_RevisionFormatting" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="raf" type="CT_RevisionAutoFormatting" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rdn" type="CT_RevisionDefinedName" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcmt" type="CT_RevisionComment" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rqt" type="CT_RevisionQueryTableField" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcft" type="CT_RevisionConflict" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:complexType> + <xsd:attributeGroup name="AG_RevData"> + <xsd:attribute name="rId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="ua" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ra" type="xsd:boolean" use="optional" default="false"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_RevisionHeader"> + <xsd:sequence> + <xsd:element name="sheetIdMap" minOccurs="1" maxOccurs="1" type="CT_SheetIdMap"/> + <xsd:element name="reviewedList" minOccurs="0" maxOccurs="1" type="CT_ReviewedRevisions"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="dateTime" type="xsd:dateTime" use="required"/> + <xsd:attribute name="maxSheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="userName" type="s:ST_Xstring" use="required"/> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="minRId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="maxRId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetIdMap"> + <xsd:sequence> + <xsd:element name="sheetId" type="CT_SheetId" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetId"> + <xsd:attribute name="val" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ReviewedRevisions"> + <xsd:sequence> + <xsd:element name="reviewed" type="CT_Reviewed" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Reviewed"> + <xsd:attribute name="rId" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_UndoInfo"> + <xsd:attribute name="index" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="exp" type="ST_FormulaExpression" use="required"/> + <xsd:attribute name="ref3D" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="array" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="v" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="nf" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="cs" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="dr" type="ST_RefA" use="required"/> + <xsd:attribute name="dn" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="r" type="ST_CellRef" use="optional"/> + <xsd:attribute name="sId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionRowColumn"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="undo" type="CT_UndoInfo" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcc" type="CT_RevisionCellChange" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rfmt" type="CT_RevisionFormatting" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="eol" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute name="action" type="ST_rwColActionType" use="required"/> + <xsd:attribute name="edge" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionMove"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="undo" type="CT_UndoInfo" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rcc" type="CT_RevisionCellChange" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rfmt" type="CT_RevisionFormatting" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="source" type="ST_Ref" use="required"/> + <xsd:attribute name="destination" type="ST_Ref" use="required"/> + <xsd:attribute name="sourceSheetId" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionCustomView"> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="action" type="ST_RevisionAction" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionSheetRename"> + <xsd:sequence> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="oldName" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="newName" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionInsertSheet"> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="sheetPosition" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionCellChange"> + <xsd:sequence> + <xsd:element name="oc" type="CT_Cell" minOccurs="0" maxOccurs="1"/> + <xsd:element name="nc" type="CT_Cell" minOccurs="1" maxOccurs="1"/> + <xsd:element name="odxf" type="CT_Dxf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ndxf" type="CT_Dxf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="odxf" type="xsd:boolean" default="false"/> + <xsd:attribute name="xfDxf" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="s" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="dxf" type="xsd:boolean" default="false"/> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + <xsd:attribute name="quotePrefix" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="oldQuotePrefix" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ph" type="xsd:boolean" default="false"/> + <xsd:attribute name="oldPh" type="xsd:boolean" default="false"/> + <xsd:attribute name="endOfListFormulaUpdate" type="xsd:boolean" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionFormatting"> + <xsd:sequence> + <xsd:element name="dxf" type="CT_Dxf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="xfDxf" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="s" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="sqref" type="ST_Sqref" use="required"/> + <xsd:attribute name="start" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="length" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionAutoFormatting"> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attributeGroup ref="AG_AutoFormat"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionComment"> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="cell" type="ST_CellRef" use="required"/> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="action" type="ST_RevisionAction" default="add"/> + <xsd:attribute name="alwaysShow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="old" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="hiddenRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="hiddenColumn" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="author" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="oldLength" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="newLength" type="xsd:unsignedInt" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionDefinedName"> + <xsd:sequence> + <xsd:element name="formula" type="ST_Formula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oldFormula" type="ST_Formula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="localSheetId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="customView" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="function" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="oldFunction" type="xsd:boolean" default="false"/> + <xsd:attribute name="functionGroupId" type="xsd:unsignedByte" use="optional"/> + <xsd:attribute name="oldFunctionGroupId" type="xsd:unsignedByte" use="optional"/> + <xsd:attribute name="shortcutKey" type="xsd:unsignedByte" use="optional"/> + <xsd:attribute name="oldShortcutKey" type="xsd:unsignedByte" use="optional"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="oldHidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="customMenu" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oldCustomMenu" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="description" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oldDescription" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="help" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oldHelp" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="statusBar" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oldStatusBar" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="comment" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oldComment" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionConflict"> + <xsd:attributeGroup ref="AG_RevData"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RevisionQueryTableField"> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute name="fieldId" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_rwColActionType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="insertRow"/> + <xsd:enumeration value="deleteRow"/> + <xsd:enumeration value="insertCol"/> + <xsd:enumeration value="deleteCol"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_RevisionAction"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="add"/> + <xsd:enumeration value="delete"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FormulaExpression"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="ref"/> + <xsd:enumeration value="refError"/> + <xsd:enumeration value="area"/> + <xsd:enumeration value="areaError"/> + <xsd:enumeration value="computedArea"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="users" type="CT_Users"/> + <xsd:complexType name="CT_Users"> + <xsd:sequence> + <xsd:element name="userInfo" minOccurs="0" maxOccurs="256" type="CT_SharedUser"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SharedUser"> + <xsd:sequence> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="id" type="xsd:int" use="required"/> + <xsd:attribute name="dateTime" type="xsd:dateTime" use="required"/> + </xsd:complexType> + <xsd:element name="worksheet" type="CT_Worksheet"/> + <xsd:element name="chartsheet" type="CT_Chartsheet"/> + <xsd:element name="dialogsheet" type="CT_Dialogsheet"/> + <xsd:complexType name="CT_Macrosheet"> + <xsd:sequence> + <xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dimension" type="CT_SheetDimension" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetViews" type="CT_SheetViews" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetFormatPr" type="CT_SheetFormatPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cols" type="CT_Cols" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="sheetData" type="CT_SheetData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sheetProtection" type="CT_SheetProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sortState" type="CT_SortState" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dataConsolidate" type="CT_DataConsolidate" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customSheetViews" type="CT_CustomSheetViews" minOccurs="0" maxOccurs="1"/> + <xsd:element name="phoneticPr" type="CT_PhoneticPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="conditionalFormatting" type="CT_ConditionalFormatting" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rowBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="colBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customProperties" type="CT_CustomProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawing" type="CT_Drawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawing" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawingHF" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/> + <xsd:element name="picture" type="CT_SheetBackgroundPicture" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oleObjects" type="CT_OleObjects" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Dialogsheet"> + <xsd:sequence> + <xsd:element name="sheetPr" minOccurs="0" type="CT_SheetPr"/> + <xsd:element name="sheetViews" minOccurs="0" type="CT_SheetViews"/> + <xsd:element name="sheetFormatPr" minOccurs="0" type="CT_SheetFormatPr"/> + <xsd:element name="sheetProtection" type="CT_SheetProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customSheetViews" minOccurs="0" type="CT_CustomSheetViews"/> + <xsd:element name="printOptions" minOccurs="0" type="CT_PrintOptions"/> + <xsd:element name="pageMargins" minOccurs="0" type="CT_PageMargins"/> + <xsd:element name="pageSetup" minOccurs="0" type="CT_PageSetup"/> + <xsd:element name="headerFooter" minOccurs="0" type="CT_HeaderFooter"/> + <xsd:element name="drawing" minOccurs="0" type="CT_Drawing"/> + <xsd:element name="legacyDrawing" minOccurs="0" type="CT_LegacyDrawing"/> + <xsd:element name="legacyDrawingHF" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oleObjects" type="CT_OleObjects" minOccurs="0" maxOccurs="1"/> + <xsd:element name="controls" type="CT_Controls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Worksheet"> + <xsd:sequence> + <xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dimension" type="CT_SheetDimension" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetViews" type="CT_SheetViews" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetFormatPr" type="CT_SheetFormatPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cols" type="CT_Cols" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="sheetData" type="CT_SheetData" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sheetCalcPr" type="CT_SheetCalcPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetProtection" type="CT_SheetProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="protectedRanges" type="CT_ProtectedRanges" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scenarios" type="CT_Scenarios" minOccurs="0" maxOccurs="1"/> + <xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sortState" type="CT_SortState" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dataConsolidate" type="CT_DataConsolidate" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customSheetViews" type="CT_CustomSheetViews" minOccurs="0" maxOccurs="1"/> + <xsd:element name="mergeCells" type="CT_MergeCells" minOccurs="0" maxOccurs="1"/> + <xsd:element name="phoneticPr" type="CT_PhoneticPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="conditionalFormatting" type="CT_ConditionalFormatting" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="dataValidations" type="CT_DataValidations" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hyperlinks" type="CT_Hyperlinks" minOccurs="0" maxOccurs="1"/> + <xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rowBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="colBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customProperties" type="CT_CustomProperties" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cellWatches" type="CT_CellWatches" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ignoredErrors" type="CT_IgnoredErrors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smartTags" type="CT_SmartTags" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawing" type="CT_Drawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawing" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawingHF" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/> + <xsd:element name="picture" type="CT_SheetBackgroundPicture" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oleObjects" type="CT_OleObjects" minOccurs="0" maxOccurs="1"/> + <xsd:element name="controls" type="CT_Controls" minOccurs="0" maxOccurs="1"/> + <xsd:element name="webPublishItems" type="CT_WebPublishItems" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tableParts" type="CT_TableParts" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SheetData"> + <xsd:sequence> + <xsd:element name="row" type="CT_Row" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SheetCalcPr"> + <xsd:attribute name="fullCalcOnLoad" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetFormatPr"> + <xsd:attribute name="baseColWidth" type="xsd:unsignedInt" use="optional" default="8"/> + <xsd:attribute name="defaultColWidth" type="xsd:double" use="optional"/> + <xsd:attribute name="defaultRowHeight" type="xsd:double" use="required"/> + <xsd:attribute name="customHeight" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="zeroHeight" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="thickTop" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="thickBottom" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="outlineLevelRow" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="outlineLevelCol" type="xsd:unsignedByte" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Cols"> + <xsd:sequence> + <xsd:element name="col" type="CT_Col" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Col"> + <xsd:attribute name="min" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="max" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="width" type="xsd:double" use="optional"/> + <xsd:attribute name="style" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="bestFit" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="customWidth" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="phonetic" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="outlineLevel" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="collapsed" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_CellSpan"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:simpleType name="ST_CellSpans"> + <xsd:list itemType="ST_CellSpan"/> + </xsd:simpleType> + <xsd:complexType name="CT_Row"> + <xsd:sequence> + <xsd:element name="c" type="CT_Cell" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="r" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="spans" type="ST_CellSpans" use="optional"/> + <xsd:attribute name="s" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="customFormat" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ht" type="xsd:double" use="optional"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="customHeight" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="outlineLevel" type="xsd:unsignedByte" use="optional" default="0"/> + <xsd:attribute name="collapsed" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="thickTop" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="thickBot" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ph" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Cell"> + <xsd:sequence> + <xsd:element name="f" type="CT_CellFormula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="is" type="CT_Rst" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="r" type="ST_CellRef" use="optional"/> + <xsd:attribute name="s" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="t" type="ST_CellType" use="optional" default="n"/> + <xsd:attribute name="cm" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="vm" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="ph" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_CellType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="b"/> + <xsd:enumeration value="n"/> + <xsd:enumeration value="e"/> + <xsd:enumeration value="s"/> + <xsd:enumeration value="str"/> + <xsd:enumeration value="inlineStr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CellFormulaType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="array"/> + <xsd:enumeration value="dataTable"/> + <xsd:enumeration value="shared"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SheetPr"> + <xsd:sequence> + <xsd:element name="tabColor" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="outlinePr" type="CT_OutlinePr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetUpPr" type="CT_PageSetUpPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="syncHorizontal" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="syncVertical" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="syncRef" type="ST_Ref" use="optional"/> + <xsd:attribute name="transitionEvaluation" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="transitionEntry" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="published" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="codeName" type="xsd:string" use="optional"/> + <xsd:attribute name="filterMode" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="enableFormatConditionsCalculation" type="xsd:boolean" use="optional" + default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetDimension"> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetViews"> + <xsd:sequence> + <xsd:element name="sheetView" type="CT_SheetView" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SheetView"> + <xsd:sequence> + <xsd:element name="pane" type="CT_Pane" minOccurs="0" maxOccurs="1"/> + <xsd:element name="selection" type="CT_Selection" minOccurs="0" maxOccurs="4"/> + <xsd:element name="pivotSelection" type="CT_PivotSelection" minOccurs="0" maxOccurs="4"/> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="windowProtection" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showFormulas" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showGridLines" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showRowColHeaders" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showZeros" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="rightToLeft" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="tabSelected" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showRuler" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showOutlineSymbols" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="defaultGridColor" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showWhiteSpace" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="view" type="ST_SheetViewType" use="optional" default="normal"/> + <xsd:attribute name="topLeftCell" type="ST_CellRef" use="optional"/> + <xsd:attribute name="colorId" type="xsd:unsignedInt" use="optional" default="64"/> + <xsd:attribute name="zoomScale" type="xsd:unsignedInt" use="optional" default="100"/> + <xsd:attribute name="zoomScaleNormal" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="zoomScaleSheetLayoutView" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="zoomScalePageLayoutView" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="workbookViewId" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Pane"> + <xsd:attribute name="xSplit" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="ySplit" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="topLeftCell" type="ST_CellRef" use="optional"/> + <xsd:attribute name="activePane" type="ST_Pane" use="optional" default="topLeft"/> + <xsd:attribute name="state" type="ST_PaneState" use="optional" default="split"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotSelection"> + <xsd:sequence> + <xsd:element name="pivotArea" type="CT_PivotArea"/> + </xsd:sequence> + <xsd:attribute name="pane" type="ST_Pane" use="optional" default="topLeft"/> + <xsd:attribute name="showHeader" type="xsd:boolean" default="false"/> + <xsd:attribute name="label" type="xsd:boolean" default="false"/> + <xsd:attribute name="data" type="xsd:boolean" default="false"/> + <xsd:attribute name="extendable" type="xsd:boolean" default="false"/> + <xsd:attribute name="count" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="axis" type="ST_Axis" use="optional"/> + <xsd:attribute name="dimension" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="start" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="min" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="max" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="activeRow" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="activeCol" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="previousRow" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="previousCol" type="xsd:unsignedInt" default="0"/> + <xsd:attribute name="click" type="xsd:unsignedInt" default="0"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Selection"> + <xsd:attribute name="pane" type="ST_Pane" use="optional" default="topLeft"/> + <xsd:attribute name="activeCell" type="ST_CellRef" use="optional"/> + <xsd:attribute name="activeCellId" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="sqref" type="ST_Sqref" use="optional" default="A1"/> + </xsd:complexType> + <xsd:simpleType name="ST_Pane"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="bottomRight"/> + <xsd:enumeration value="topRight"/> + <xsd:enumeration value="bottomLeft"/> + <xsd:enumeration value="topLeft"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PageBreak"> + <xsd:sequence> + <xsd:element name="brk" type="CT_Break" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="manualBreakCount" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Break"> + <xsd:attribute name="id" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="min" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="max" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="man" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pt" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_SheetViewType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="pageBreakPreview"/> + <xsd:enumeration value="pageLayout"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_OutlinePr"> + <xsd:attribute name="applyStyles" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="summaryBelow" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="summaryRight" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showOutlineSymbols" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_PageSetUpPr"> + <xsd:attribute name="autoPageBreaks" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="fitToPage" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_DataConsolidate"> + <xsd:sequence> + <xsd:element name="dataRefs" type="CT_DataRefs" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="function" type="ST_DataConsolidateFunction" use="optional" default="sum"/> + <xsd:attribute name="startLabels" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="leftLabels" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="topLabels" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="link" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_DataConsolidateFunction"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="average"/> + <xsd:enumeration value="count"/> + <xsd:enumeration value="countNums"/> + <xsd:enumeration value="max"/> + <xsd:enumeration value="min"/> + <xsd:enumeration value="product"/> + <xsd:enumeration value="stdDev"/> + <xsd:enumeration value="stdDevp"/> + <xsd:enumeration value="sum"/> + <xsd:enumeration value="var"/> + <xsd:enumeration value="varp"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DataRefs"> + <xsd:sequence> + <xsd:element name="dataRef" type="CT_DataRef" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DataRef"> + <xsd:attribute name="ref" type="ST_Ref" use="optional"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sheet" type="s:ST_Xstring" use="optional"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_MergeCells"> + <xsd:sequence> + <xsd:element name="mergeCell" type="CT_MergeCell" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_MergeCell"> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SmartTags"> + <xsd:sequence> + <xsd:element name="cellSmartTags" type="CT_CellSmartTags" minOccurs="1" maxOccurs="unbounded" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CellSmartTags"> + <xsd:sequence> + <xsd:element name="cellSmartTag" type="CT_CellSmartTag" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="r" type="ST_CellRef" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CellSmartTag"> + <xsd:sequence> + <xsd:element name="cellSmartTagPr" minOccurs="0" maxOccurs="unbounded" + type="CT_CellSmartTagPr"/> + </xsd:sequence> + <xsd:attribute name="type" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="deleted" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="xmlBased" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CellSmartTagPr"> + <xsd:attribute name="key" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="val" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Drawing"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_LegacyDrawing"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DrawingHF"> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="lho" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="lhe" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="lhf" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cho" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="che" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="chf" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rho" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rhe" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rhf" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="lfo" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="lfe" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="lff" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cfo" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cfe" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="cff" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rfo" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rfe" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rff" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomSheetViews"> + <xsd:sequence> + <xsd:element name="customSheetView" minOccurs="1" maxOccurs="unbounded" + type="CT_CustomSheetView"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomSheetView"> + <xsd:sequence> + <xsd:element name="pane" type="CT_Pane" minOccurs="0" maxOccurs="1"/> + <xsd:element name="selection" type="CT_Selection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rowBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="colBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/> + <xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="scale" type="xsd:unsignedInt" default="100"/> + <xsd:attribute name="colorId" type="xsd:unsignedInt" default="64"/> + <xsd:attribute name="showPageBreaks" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showFormulas" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showGridLines" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showRowCol" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="outlineSymbols" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="zeroValues" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="fitToPage" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="printArea" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="filter" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showAutoFilter" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="hiddenRows" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="hiddenColumns" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="state" type="ST_SheetState" default="visible"/> + <xsd:attribute name="filterUnique" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="view" type="ST_SheetViewType" default="normal"/> + <xsd:attribute name="showRuler" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="topLeftCell" type="ST_CellRef" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DataValidations"> + <xsd:sequence> + <xsd:element name="dataValidation" type="CT_DataValidation" minOccurs="1" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="disablePrompts" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="xWindow" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="yWindow" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DataValidation"> + <xsd:sequence> + <xsd:element name="formula1" type="ST_Formula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="formula2" type="ST_Formula" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_DataValidationType" use="optional" default="none"/> + <xsd:attribute name="errorStyle" type="ST_DataValidationErrorStyle" use="optional" + default="stop"/> + <xsd:attribute name="imeMode" type="ST_DataValidationImeMode" use="optional" default="noControl"/> + <xsd:attribute name="operator" type="ST_DataValidationOperator" use="optional" default="between"/> + <xsd:attribute name="allowBlank" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showDropDown" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showInputMessage" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showErrorMessage" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="errorTitle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="error" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="promptTitle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="prompt" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sqref" type="ST_Sqref" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DataValidationType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="whole"/> + <xsd:enumeration value="decimal"/> + <xsd:enumeration value="list"/> + <xsd:enumeration value="date"/> + <xsd:enumeration value="time"/> + <xsd:enumeration value="textLength"/> + <xsd:enumeration value="custom"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DataValidationOperator"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="between"/> + <xsd:enumeration value="notBetween"/> + <xsd:enumeration value="equal"/> + <xsd:enumeration value="notEqual"/> + <xsd:enumeration value="lessThan"/> + <xsd:enumeration value="lessThanOrEqual"/> + <xsd:enumeration value="greaterThan"/> + <xsd:enumeration value="greaterThanOrEqual"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DataValidationErrorStyle"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="stop"/> + <xsd:enumeration value="warning"/> + <xsd:enumeration value="information"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DataValidationImeMode"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="noControl"/> + <xsd:enumeration value="off"/> + <xsd:enumeration value="on"/> + <xsd:enumeration value="disabled"/> + <xsd:enumeration value="hiragana"/> + <xsd:enumeration value="fullKatakana"/> + <xsd:enumeration value="halfKatakana"/> + <xsd:enumeration value="fullAlpha"/> + <xsd:enumeration value="halfAlpha"/> + <xsd:enumeration value="fullHangul"/> + <xsd:enumeration value="halfHangul"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CfType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="expression"/> + <xsd:enumeration value="cellIs"/> + <xsd:enumeration value="colorScale"/> + <xsd:enumeration value="dataBar"/> + <xsd:enumeration value="iconSet"/> + <xsd:enumeration value="top10"/> + <xsd:enumeration value="uniqueValues"/> + <xsd:enumeration value="duplicateValues"/> + <xsd:enumeration value="containsText"/> + <xsd:enumeration value="notContainsText"/> + <xsd:enumeration value="beginsWith"/> + <xsd:enumeration value="endsWith"/> + <xsd:enumeration value="containsBlanks"/> + <xsd:enumeration value="notContainsBlanks"/> + <xsd:enumeration value="containsErrors"/> + <xsd:enumeration value="notContainsErrors"/> + <xsd:enumeration value="timePeriod"/> + <xsd:enumeration value="aboveAverage"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TimePeriod"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="today"/> + <xsd:enumeration value="yesterday"/> + <xsd:enumeration value="tomorrow"/> + <xsd:enumeration value="last7Days"/> + <xsd:enumeration value="thisMonth"/> + <xsd:enumeration value="lastMonth"/> + <xsd:enumeration value="nextMonth"/> + <xsd:enumeration value="thisWeek"/> + <xsd:enumeration value="lastWeek"/> + <xsd:enumeration value="nextWeek"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_ConditionalFormattingOperator"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="lessThan"/> + <xsd:enumeration value="lessThanOrEqual"/> + <xsd:enumeration value="equal"/> + <xsd:enumeration value="notEqual"/> + <xsd:enumeration value="greaterThanOrEqual"/> + <xsd:enumeration value="greaterThan"/> + <xsd:enumeration value="between"/> + <xsd:enumeration value="notBetween"/> + <xsd:enumeration value="containsText"/> + <xsd:enumeration value="notContains"/> + <xsd:enumeration value="beginsWith"/> + <xsd:enumeration value="endsWith"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CfvoType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="num"/> + <xsd:enumeration value="percent"/> + <xsd:enumeration value="max"/> + <xsd:enumeration value="min"/> + <xsd:enumeration value="formula"/> + <xsd:enumeration value="percentile"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ConditionalFormatting"> + <xsd:sequence> + <xsd:element name="cfRule" type="CT_CfRule" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="pivot" type="xsd:boolean" default="false"/> + <xsd:attribute name="sqref" type="ST_Sqref"/> + </xsd:complexType> + <xsd:complexType name="CT_CfRule"> + <xsd:sequence> + <xsd:element name="formula" type="ST_Formula" minOccurs="0" maxOccurs="3"/> + <xsd:element name="colorScale" type="CT_ColorScale" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dataBar" type="CT_DataBar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="iconSet" type="CT_IconSet" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_CfType"/> + <xsd:attribute name="dxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="priority" type="xsd:int" use="required"/> + <xsd:attribute name="stopIfTrue" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="aboveAverage" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="percent" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="bottom" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="operator" type="ST_ConditionalFormattingOperator" use="optional"/> + <xsd:attribute name="text" type="xsd:string" use="optional"/> + <xsd:attribute name="timePeriod" type="ST_TimePeriod" use="optional"/> + <xsd:attribute name="rank" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="stdDev" type="xsd:int" use="optional"/> + <xsd:attribute name="equalAverage" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Hyperlinks"> + <xsd:sequence> + <xsd:element name="hyperlink" type="CT_Hyperlink" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Hyperlink"> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute ref="r:id" use="optional"/> + <xsd:attribute name="location" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="tooltip" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="display" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CellFormula"> + <xsd:simpleContent> + <xsd:extension base="ST_Formula"> + <xsd:attribute name="t" type="ST_CellFormulaType" use="optional" default="normal"/> + <xsd:attribute name="aca" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ref" type="ST_Ref" use="optional"/> + <xsd:attribute name="dt2D" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="dtr" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="del1" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="del2" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="r1" type="ST_CellRef" use="optional"/> + <xsd:attribute name="r2" type="ST_CellRef" use="optional"/> + <xsd:attribute name="ca" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="si" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bx" type="xsd:boolean" use="optional" default="false"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:complexType name="CT_ColorScale"> + <xsd:sequence> + <xsd:element name="cfvo" type="CT_Cfvo" minOccurs="2" maxOccurs="unbounded"/> + <xsd:element name="color" type="CT_Color" minOccurs="2" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DataBar"> + <xsd:sequence> + <xsd:element name="cfvo" type="CT_Cfvo" minOccurs="2" maxOccurs="2"/> + <xsd:element name="color" type="CT_Color" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="minLength" type="xsd:unsignedInt" use="optional" default="10"/> + <xsd:attribute name="maxLength" type="xsd:unsignedInt" use="optional" default="90"/> + <xsd:attribute name="showValue" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_IconSet"> + <xsd:sequence> + <xsd:element name="cfvo" type="CT_Cfvo" minOccurs="2" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="iconSet" type="ST_IconSetType" use="optional" default="3TrafficLights1"/> + <xsd:attribute name="showValue" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="percent" type="xsd:boolean" default="true"/> + <xsd:attribute name="reverse" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Cfvo"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_CfvoType" use="required"/> + <xsd:attribute name="val" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="gte" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_PageMargins"> + <xsd:attribute name="left" type="xsd:double" use="required"/> + <xsd:attribute name="right" type="xsd:double" use="required"/> + <xsd:attribute name="top" type="xsd:double" use="required"/> + <xsd:attribute name="bottom" type="xsd:double" use="required"/> + <xsd:attribute name="header" type="xsd:double" use="required"/> + <xsd:attribute name="footer" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PrintOptions"> + <xsd:attribute name="horizontalCentered" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="verticalCentered" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="headings" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="gridLines" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="gridLinesSet" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_PageSetup"> + <xsd:attribute name="paperSize" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="paperHeight" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="paperWidth" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="scale" type="xsd:unsignedInt" use="optional" default="100"/> + <xsd:attribute name="firstPageNumber" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="fitToWidth" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="fitToHeight" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="pageOrder" type="ST_PageOrder" use="optional" default="downThenOver"/> + <xsd:attribute name="orientation" type="ST_Orientation" use="optional" default="default"/> + <xsd:attribute name="usePrinterDefaults" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="blackAndWhite" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="draft" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="cellComments" type="ST_CellComments" use="optional" default="none"/> + <xsd:attribute name="useFirstPageNumber" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="errors" type="ST_PrintError" use="optional" default="displayed"/> + <xsd:attribute name="horizontalDpi" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="verticalDpi" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="copies" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PageOrder"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="downThenOver"/> + <xsd:enumeration value="overThenDown"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Orientation"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="default"/> + <xsd:enumeration value="portrait"/> + <xsd:enumeration value="landscape"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_CellComments"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="asDisplayed"/> + <xsd:enumeration value="atEnd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_HeaderFooter"> + <xsd:sequence> + <xsd:element name="oddHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oddFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="evenHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="evenFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstHeader" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + <xsd:element name="firstFooter" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="differentOddEven" type="xsd:boolean" default="false"/> + <xsd:attribute name="differentFirst" type="xsd:boolean" default="false"/> + <xsd:attribute name="scaleWithDoc" type="xsd:boolean" default="true"/> + <xsd:attribute name="alignWithMargins" type="xsd:boolean" default="true"/> + </xsd:complexType> + <xsd:simpleType name="ST_PrintError"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="displayed"/> + <xsd:enumeration value="blank"/> + <xsd:enumeration value="dash"/> + <xsd:enumeration value="NA"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Scenarios"> + <xsd:sequence> + <xsd:element name="scenario" type="CT_Scenario" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="current" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="show" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="sqref" type="ST_Sqref" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetProtection"> + <xsd:attribute name="password" type="ST_UnsignedShortHex" use="optional"/> + <xsd:attribute name="algorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="sheet" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="objects" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="scenarios" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="formatCells" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="formatColumns" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="formatRows" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="insertColumns" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="insertRows" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="insertHyperlinks" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="deleteColumns" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="deleteRows" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="selectLockedCells" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="sort" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoFilter" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="pivotTables" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="selectUnlockedCells" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ProtectedRanges"> + <xsd:sequence> + <xsd:element name="protectedRange" type="CT_ProtectedRange" minOccurs="1" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ProtectedRange"> + <xsd:sequence> + <xsd:element name="securityDescriptor" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="password" type="ST_UnsignedShortHex" use="optional"/> + <xsd:attribute name="sqref" type="ST_Sqref" use="required"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="securityDescriptor" type="xsd:string" use="optional"/> + <xsd:attribute name="algorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinCount" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Scenario"> + <xsd:sequence> + <xsd:element name="inputCells" type="CT_InputCells" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="locked" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="user" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="comment" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_InputCells"> + <xsd:attribute name="r" type="ST_CellRef" use="required"/> + <xsd:attribute name="deleted" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="undone" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="val" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CellWatches"> + <xsd:sequence> + <xsd:element name="cellWatch" type="CT_CellWatch" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CellWatch"> + <xsd:attribute name="r" type="ST_CellRef" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Chartsheet"> + <xsd:sequence> + <xsd:element name="sheetPr" type="CT_ChartsheetPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetViews" type="CT_ChartsheetViews" minOccurs="1" maxOccurs="1"/> + <xsd:element name="sheetProtection" type="CT_ChartsheetProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customSheetViews" type="CT_CustomChartsheetViews" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="pageMargins" minOccurs="0" type="CT_PageMargins"/> + <xsd:element name="pageSetup" type="CT_CsPageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headerFooter" minOccurs="0" type="CT_HeaderFooter"/> + <xsd:element name="drawing" type="CT_Drawing" minOccurs="1" maxOccurs="1"/> + <xsd:element name="legacyDrawing" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="legacyDrawingHF" type="CT_LegacyDrawing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/> + <xsd:element name="picture" type="CT_SheetBackgroundPicture" minOccurs="0" maxOccurs="1"/> + <xsd:element name="webPublishItems" type="CT_WebPublishItems" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ChartsheetPr"> + <xsd:sequence> + <xsd:element name="tabColor" type="CT_Color" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="published" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="codeName" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ChartsheetViews"> + <xsd:sequence> + <xsd:element name="sheetView" type="CT_ChartsheetView" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ChartsheetView"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="tabSelected" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="zoomScale" type="xsd:unsignedInt" default="100" use="optional"/> + <xsd:attribute name="workbookViewId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="zoomToFit" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ChartsheetProtection"> + <xsd:attribute name="password" type="ST_UnsignedShortHex" use="optional"/> + <xsd:attribute name="algorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="content" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="objects" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CsPageSetup"> + <xsd:attribute name="paperSize" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="paperHeight" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="paperWidth" type="s:ST_PositiveUniversalMeasure" use="optional"/> + <xsd:attribute name="firstPageNumber" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="orientation" type="ST_Orientation" use="optional" default="default"/> + <xsd:attribute name="usePrinterDefaults" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="blackAndWhite" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="draft" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="useFirstPageNumber" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="horizontalDpi" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="verticalDpi" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="copies" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomChartsheetViews"> + <xsd:sequence> + <xsd:element name="customSheetView" minOccurs="0" maxOccurs="unbounded" + type="CT_CustomChartsheetView"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomChartsheetView"> + <xsd:sequence> + <xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pageSetup" type="CT_CsPageSetup" minOccurs="0" maxOccurs="1"/> + <xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="scale" type="xsd:unsignedInt" default="100"/> + <xsd:attribute name="state" type="ST_SheetState" default="visible"/> + <xsd:attribute name="zoomToFit" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomProperties"> + <xsd:sequence> + <xsd:element name="customPr" type="CT_CustomProperty" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomProperty"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_OleObjects"> + <xsd:sequence> + <xsd:element name="oleObject" type="CT_OleObject" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OleObject"> + <xsd:sequence> + <xsd:element name="objectPr" type="CT_ObjectPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="progId" type="xsd:string" use="optional"/> + <xsd:attribute name="dvAspect" type="ST_DvAspect" use="optional" default="DVASPECT_CONTENT"/> + <xsd:attribute name="link" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="oleUpdate" type="ST_OleUpdate" use="optional"/> + <xsd:attribute name="autoLoad" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="shapeId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ObjectPr"> + <xsd:sequence> + <xsd:element name="anchor" type="CT_ObjectAnchor" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="locked" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="defaultSize" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="print" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="disabled" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="uiObject" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoFill" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoLine" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoPict" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="macro" type="ST_Formula" use="optional"/> + <xsd:attribute name="altText" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="dde" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_DvAspect"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="DVASPECT_CONTENT"/> + <xsd:enumeration value="DVASPECT_ICON"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_OleUpdate"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="OLEUPDATE_ALWAYS"/> + <xsd:enumeration value="OLEUPDATE_ONCALL"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_WebPublishItems"> + <xsd:sequence> + <xsd:element name="webPublishItem" type="CT_WebPublishItem" minOccurs="1" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_WebPublishItem"> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="divId" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="sourceType" type="ST_WebSourceType" use="required"/> + <xsd:attribute name="sourceRef" type="ST_Ref" use="optional"/> + <xsd:attribute name="sourceObject" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="destinationFile" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="title" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="autoRepublish" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_Controls"> + <xsd:sequence> + <xsd:element name="control" type="CT_Control" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Control"> + <xsd:sequence> + <xsd:element name="controlPr" type="CT_ControlPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="shapeId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="name" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ControlPr"> + <xsd:sequence> + <xsd:element name="anchor" type="CT_ObjectAnchor" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="locked" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="defaultSize" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="print" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="disabled" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="recalcAlways" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="uiObject" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoFill" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoLine" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="autoPict" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="macro" type="ST_Formula" use="optional"/> + <xsd:attribute name="altText" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="linkedCell" type="ST_Formula" use="optional"/> + <xsd:attribute name="listFillRange" type="ST_Formula" use="optional"/> + <xsd:attribute name="cf" type="s:ST_Xstring" use="optional" default="pict"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_WebSourceType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="sheet"/> + <xsd:enumeration value="printArea"/> + <xsd:enumeration value="autoFilter"/> + <xsd:enumeration value="range"/> + <xsd:enumeration value="chart"/> + <xsd:enumeration value="pivotTable"/> + <xsd:enumeration value="query"/> + <xsd:enumeration value="label"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_IgnoredErrors"> + <xsd:sequence> + <xsd:element name="ignoredError" type="CT_IgnoredError" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_IgnoredError"> + <xsd:attribute name="sqref" type="ST_Sqref" use="required"/> + <xsd:attribute name="evalError" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="twoDigitTextYear" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="numberStoredAsText" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="formula" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="formulaRange" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="unlockedFormula" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="emptyCellReference" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="listDataValidation" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="calculatedColumn" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:simpleType name="ST_PaneState"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="split"/> + <xsd:enumeration value="frozen"/> + <xsd:enumeration value="frozenSplit"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TableParts"> + <xsd:sequence> + <xsd:element name="tablePart" type="CT_TablePart" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TablePart"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:element name="metadata" type="CT_Metadata"/> + <xsd:complexType name="CT_Metadata"> + <xsd:sequence> + <xsd:element name="metadataTypes" type="CT_MetadataTypes" minOccurs="0" maxOccurs="1"/> + <xsd:element name="metadataStrings" type="CT_MetadataStrings" minOccurs="0" maxOccurs="1"/> + <xsd:element name="mdxMetadata" type="CT_MdxMetadata" minOccurs="0" maxOccurs="1"/> + <xsd:element name="futureMetadata" type="CT_FutureMetadata" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="cellMetadata" type="CT_MetadataBlocks" minOccurs="0" maxOccurs="1"/> + <xsd:element name="valueMetadata" type="CT_MetadataBlocks" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MetadataTypes"> + <xsd:sequence> + <xsd:element name="metadataType" type="CT_MetadataType" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_MetadataType"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="minSupportedVersion" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="ghostRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="ghostCol" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="edit" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="delete" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="copy" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteAll" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteFormulas" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteValues" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteFormats" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteComments" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteDataValidation" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteBorders" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteColWidths" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pasteNumberFormats" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="merge" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="splitFirst" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="splitAll" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="rowColShift" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="clearAll" type="xsd:boolean" default="false"/> + <xsd:attribute name="clearFormats" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="clearContents" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="clearComments" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="assign" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="coerce" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="adjust" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="cellMeta" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_MetadataBlocks"> + <xsd:sequence> + <xsd:element name="bk" type="CT_MetadataBlock" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_MetadataBlock"> + <xsd:sequence> + <xsd:element name="rc" type="CT_MetadataRecord" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MetadataRecord"> + <xsd:attribute name="t" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="v" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FutureMetadata"> + <xsd:sequence> + <xsd:element name="bk" type="CT_FutureMetadataBlock" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_FutureMetadataBlock"> + <xsd:sequence> + <xsd:element name="extLst" minOccurs="0" maxOccurs="1" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MdxMetadata"> + <xsd:sequence> + <xsd:element name="mdx" type="CT_Mdx" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Mdx"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="t" type="CT_MdxTuple"/> + <xsd:element name="ms" type="CT_MdxSet"/> + <xsd:element name="p" type="CT_MdxMemeberProp"/> + <xsd:element name="k" type="CT_MdxKPI"/> + </xsd:choice> + <xsd:attribute name="n" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="f" type="ST_MdxFunctionType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MdxFunctionType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="m"/> + <xsd:enumeration value="v"/> + <xsd:enumeration value="s"/> + <xsd:enumeration value="c"/> + <xsd:enumeration value="r"/> + <xsd:enumeration value="p"/> + <xsd:enumeration value="k"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MdxTuple"> + <xsd:sequence> + <xsd:element name="n" type="CT_MetadataStringIndex" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="c" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="ct" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="si" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="fi" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="bc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="fc" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="i" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="u" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="st" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="b" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_MdxSet"> + <xsd:sequence> + <xsd:element name="n" type="CT_MetadataStringIndex" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="ns" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="c" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="o" type="ST_MdxSetOrder" use="optional" default="u"/> + </xsd:complexType> + <xsd:simpleType name="ST_MdxSetOrder"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="u"/> + <xsd:enumeration value="a"/> + <xsd:enumeration value="d"/> + <xsd:enumeration value="aa"/> + <xsd:enumeration value="ad"/> + <xsd:enumeration value="na"/> + <xsd:enumeration value="nd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MdxMemeberProp"> + <xsd:attribute name="n" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="np" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_MdxKPI"> + <xsd:attribute name="n" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="np" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="p" type="ST_MdxKPIProperty" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MdxKPIProperty"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="v"/> + <xsd:enumeration value="g"/> + <xsd:enumeration value="s"/> + <xsd:enumeration value="t"/> + <xsd:enumeration value="w"/> + <xsd:enumeration value="m"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MetadataStringIndex"> + <xsd:attribute name="x" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="s" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_MetadataStrings"> + <xsd:sequence> + <xsd:element name="s" type="CT_XStringElement" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:element name="singleXmlCells" type="CT_SingleXmlCells"/> + <xsd:complexType name="CT_SingleXmlCells"> + <xsd:sequence> + <xsd:element name="singleXmlCell" type="CT_SingleXmlCell" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SingleXmlCell"> + <xsd:sequence> + <xsd:element name="xmlCellPr" type="CT_XmlCellPr" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="r" type="ST_CellRef" use="required"/> + <xsd:attribute name="connectionId" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_XmlCellPr"> + <xsd:sequence> + <xsd:element name="xmlPr" type="CT_XmlPr" minOccurs="1" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="uniqueName" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_XmlPr"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="mapId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="xpath" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="xmlDataType" type="ST_XmlDataType" use="required"/> + </xsd:complexType> + <xsd:element name="styleSheet" type="CT_Stylesheet"/> + <xsd:complexType name="CT_Stylesheet"> + <xsd:sequence> + <xsd:element name="numFmts" type="CT_NumFmts" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fonts" type="CT_Fonts" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fills" type="CT_Fills" minOccurs="0" maxOccurs="1"/> + <xsd:element name="borders" type="CT_Borders" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cellStyleXfs" type="CT_CellStyleXfs" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cellXfs" type="CT_CellXfs" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cellStyles" type="CT_CellStyles" minOccurs="0" maxOccurs="1"/> + <xsd:element name="dxfs" type="CT_Dxfs" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tableStyles" type="CT_TableStyles" minOccurs="0" maxOccurs="1"/> + <xsd:element name="colors" type="CT_Colors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CellAlignment"> + <xsd:attribute name="horizontal" type="ST_HorizontalAlignment" use="optional"/> + <xsd:attribute name="vertical" type="ST_VerticalAlignment" default="bottom" use="optional"/> + <xsd:attribute name="textRotation" type="ST_TextRotation" use="optional"/> + <xsd:attribute name="wrapText" type="xsd:boolean" use="optional"/> + <xsd:attribute name="indent" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="relativeIndent" type="xsd:int" use="optional"/> + <xsd:attribute name="justifyLastLine" type="xsd:boolean" use="optional"/> + <xsd:attribute name="shrinkToFit" type="xsd:boolean" use="optional"/> + <xsd:attribute name="readingOrder" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextRotation"> + <xsd:union> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger"> + <xsd:maxInclusive value="180"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType> + <xsd:restriction base="xsd:nonNegativeInteger"> + <xsd:enumeration value="255"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:union> + </xsd:simpleType> + <xsd:simpleType name="ST_BorderStyle"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="thin"/> + <xsd:enumeration value="medium"/> + <xsd:enumeration value="dashed"/> + <xsd:enumeration value="dotted"/> + <xsd:enumeration value="thick"/> + <xsd:enumeration value="double"/> + <xsd:enumeration value="hair"/> + <xsd:enumeration value="mediumDashed"/> + <xsd:enumeration value="dashDot"/> + <xsd:enumeration value="mediumDashDot"/> + <xsd:enumeration value="dashDotDot"/> + <xsd:enumeration value="mediumDashDotDot"/> + <xsd:enumeration value="slantDashDot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Borders"> + <xsd:sequence> + <xsd:element name="border" type="CT_Border" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Border"> + <xsd:sequence> + <xsd:element name="start" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="end" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="left" type="CT_BorderPr" minOccurs="0"/> + <xsd:element name="right" type="CT_BorderPr" minOccurs="0"/> + <xsd:element name="top" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bottom" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="diagonal" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="vertical" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="horizontal" type="CT_BorderPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="diagonalUp" type="xsd:boolean" use="optional"/> + <xsd:attribute name="diagonalDown" type="xsd:boolean" use="optional"/> + <xsd:attribute name="outline" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_BorderPr"> + <xsd:sequence> + <xsd:element name="color" type="CT_Color" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="style" type="ST_BorderStyle" use="optional" default="none"/> + </xsd:complexType> + <xsd:complexType name="CT_CellProtection"> + <xsd:attribute name="locked" type="xsd:boolean" use="optional"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Fonts"> + <xsd:sequence> + <xsd:element name="font" type="CT_Font" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Fills"> + <xsd:sequence> + <xsd:element name="fill" type="CT_Fill" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Fill"> + <xsd:choice minOccurs="1" maxOccurs="1"> + <xsd:element name="patternFill" type="CT_PatternFill" minOccurs="0" maxOccurs="1"/> + <xsd:element name="gradientFill" type="CT_GradientFill" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_PatternFill"> + <xsd:sequence> + <xsd:element name="fgColor" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bgColor" type="CT_Color" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="patternType" type="ST_PatternType" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Color"> + <xsd:attribute name="auto" type="xsd:boolean" use="optional"/> + <xsd:attribute name="indexed" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="rgb" type="ST_UnsignedIntHex" use="optional"/> + <xsd:attribute name="theme" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="tint" type="xsd:double" use="optional" default="0.0"/> + </xsd:complexType> + <xsd:simpleType name="ST_PatternType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="solid"/> + <xsd:enumeration value="mediumGray"/> + <xsd:enumeration value="darkGray"/> + <xsd:enumeration value="lightGray"/> + <xsd:enumeration value="darkHorizontal"/> + <xsd:enumeration value="darkVertical"/> + <xsd:enumeration value="darkDown"/> + <xsd:enumeration value="darkUp"/> + <xsd:enumeration value="darkGrid"/> + <xsd:enumeration value="darkTrellis"/> + <xsd:enumeration value="lightHorizontal"/> + <xsd:enumeration value="lightVertical"/> + <xsd:enumeration value="lightDown"/> + <xsd:enumeration value="lightUp"/> + <xsd:enumeration value="lightGrid"/> + <xsd:enumeration value="lightTrellis"/> + <xsd:enumeration value="gray125"/> + <xsd:enumeration value="gray0625"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_GradientFill"> + <xsd:sequence> + <xsd:element name="stop" type="CT_GradientStop" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_GradientType" use="optional" default="linear"/> + <xsd:attribute name="degree" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="left" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="right" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="top" type="xsd:double" use="optional" default="0"/> + <xsd:attribute name="bottom" type="xsd:double" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_GradientStop"> + <xsd:sequence> + <xsd:element name="color" type="CT_Color" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="position" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_GradientType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="linear"/> + <xsd:enumeration value="path"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HorizontalAlignment"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="general"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="right"/> + <xsd:enumeration value="fill"/> + <xsd:enumeration value="justify"/> + <xsd:enumeration value="centerContinuous"/> + <xsd:enumeration value="distributed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_VerticalAlignment"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="top"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="bottom"/> + <xsd:enumeration value="justify"/> + <xsd:enumeration value="distributed"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_NumFmts"> + <xsd:sequence> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_NumFmt"> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="required"/> + <xsd:attribute name="formatCode" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CellStyleXfs"> + <xsd:sequence> + <xsd:element name="xf" type="CT_Xf" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CellXfs"> + <xsd:sequence> + <xsd:element name="xf" type="CT_Xf" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Xf"> + <xsd:sequence> + <xsd:element name="alignment" type="CT_CellAlignment" minOccurs="0" maxOccurs="1"/> + <xsd:element name="protection" type="CT_CellProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="numFmtId" type="ST_NumFmtId" use="optional"/> + <xsd:attribute name="fontId" type="ST_FontId" use="optional"/> + <xsd:attribute name="fillId" type="ST_FillId" use="optional"/> + <xsd:attribute name="borderId" type="ST_BorderId" use="optional"/> + <xsd:attribute name="xfId" type="ST_CellStyleXfId" use="optional"/> + <xsd:attribute name="quotePrefix" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="pivotButton" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="applyNumberFormat" type="xsd:boolean" use="optional"/> + <xsd:attribute name="applyFont" type="xsd:boolean" use="optional"/> + <xsd:attribute name="applyFill" type="xsd:boolean" use="optional"/> + <xsd:attribute name="applyBorder" type="xsd:boolean" use="optional"/> + <xsd:attribute name="applyAlignment" type="xsd:boolean" use="optional"/> + <xsd:attribute name="applyProtection" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CellStyles"> + <xsd:sequence> + <xsd:element name="cellStyle" type="CT_CellStyle" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_CellStyle"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="xfId" type="ST_CellStyleXfId" use="required"/> + <xsd:attribute name="builtinId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="iLevel" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional"/> + <xsd:attribute name="customBuiltin" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Dxfs"> + <xsd:sequence> + <xsd:element name="dxf" type="CT_Dxf" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Dxf"> + <xsd:sequence> + <xsd:element name="font" type="CT_Font" minOccurs="0" maxOccurs="1"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fill" type="CT_Fill" minOccurs="0" maxOccurs="1"/> + <xsd:element name="alignment" type="CT_CellAlignment" minOccurs="0" maxOccurs="1"/> + <xsd:element name="border" type="CT_Border" minOccurs="0" maxOccurs="1"/> + <xsd:element name="protection" type="CT_CellProtection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_NumFmtId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_FontId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_FillId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_BorderId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_CellStyleXfId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:simpleType name="ST_DxfId"> + <xsd:restriction base="xsd:unsignedInt"/> + </xsd:simpleType> + <xsd:complexType name="CT_Colors"> + <xsd:sequence> + <xsd:element name="indexedColors" type="CT_IndexedColors" minOccurs="0" maxOccurs="1"/> + <xsd:element name="mruColors" type="CT_MRUColors" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_IndexedColors"> + <xsd:sequence> + <xsd:element name="rgbColor" type="CT_RgbColor" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MRUColors"> + <xsd:sequence> + <xsd:element name="color" type="CT_Color" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_RgbColor"> + <xsd:attribute name="rgb" type="ST_UnsignedIntHex" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableStyles"> + <xsd:sequence> + <xsd:element name="tableStyle" type="CT_TableStyle" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="defaultTableStyle" type="xsd:string" use="optional"/> + <xsd:attribute name="defaultPivotStyle" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableStyle"> + <xsd:sequence> + <xsd:element name="tableStyleElement" type="CT_TableStyleElement" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="pivot" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="table" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableStyleElement"> + <xsd:attribute name="type" type="ST_TableStyleType" use="required"/> + <xsd:attribute name="size" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="dxfId" type="ST_DxfId" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TableStyleType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="wholeTable"/> + <xsd:enumeration value="headerRow"/> + <xsd:enumeration value="totalRow"/> + <xsd:enumeration value="firstColumn"/> + <xsd:enumeration value="lastColumn"/> + <xsd:enumeration value="firstRowStripe"/> + <xsd:enumeration value="secondRowStripe"/> + <xsd:enumeration value="firstColumnStripe"/> + <xsd:enumeration value="secondColumnStripe"/> + <xsd:enumeration value="firstHeaderCell"/> + <xsd:enumeration value="lastHeaderCell"/> + <xsd:enumeration value="firstTotalCell"/> + <xsd:enumeration value="lastTotalCell"/> + <xsd:enumeration value="firstSubtotalColumn"/> + <xsd:enumeration value="secondSubtotalColumn"/> + <xsd:enumeration value="thirdSubtotalColumn"/> + <xsd:enumeration value="firstSubtotalRow"/> + <xsd:enumeration value="secondSubtotalRow"/> + <xsd:enumeration value="thirdSubtotalRow"/> + <xsd:enumeration value="blankRow"/> + <xsd:enumeration value="firstColumnSubheading"/> + <xsd:enumeration value="secondColumnSubheading"/> + <xsd:enumeration value="thirdColumnSubheading"/> + <xsd:enumeration value="firstRowSubheading"/> + <xsd:enumeration value="secondRowSubheading"/> + <xsd:enumeration value="thirdRowSubheading"/> + <xsd:enumeration value="pageFieldLabels"/> + <xsd:enumeration value="pageFieldValues"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_BooleanProperty"> + <xsd:attribute name="val" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:complexType name="CT_FontSize"> + <xsd:attribute name="val" type="xsd:double" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_IntProperty"> + <xsd:attribute name="val" type="xsd:int" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FontName"> + <xsd:attribute name="val" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_VerticalAlignFontProperty"> + <xsd:attribute name="val" type="s:ST_VerticalAlignRun" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FontScheme"> + <xsd:attribute name="val" type="ST_FontScheme" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_FontScheme"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="major"/> + <xsd:enumeration value="minor"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_UnderlineProperty"> + <xsd:attribute name="val" type="ST_UnderlineValues" use="optional" default="single"/> + </xsd:complexType> + <xsd:simpleType name="ST_UnderlineValues"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="single"/> + <xsd:enumeration value="double"/> + <xsd:enumeration value="singleAccounting"/> + <xsd:enumeration value="doubleAccounting"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Font"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="name" type="CT_FontName" minOccurs="0" maxOccurs="1"/> + <xsd:element name="charset" type="CT_IntProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="family" type="CT_FontFamily" minOccurs="0" maxOccurs="1"/> + <xsd:element name="b" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="i" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="strike" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="outline" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shadow" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="condense" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extend" type="CT_BooleanProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="color" type="CT_Color" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sz" type="CT_FontSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="u" type="CT_UnderlineProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="vertAlign" type="CT_VerticalAlignFontProperty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="scheme" type="CT_FontScheme" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_FontFamily"> + <xsd:attribute name="val" type="ST_FontFamily" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_FontFamily"> + <xsd:restriction base="xsd:integer"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="14"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:attributeGroup name="AG_AutoFormat"> + <xsd:attribute name="autoFormatId" type="xsd:unsignedInt"/> + <xsd:attribute name="applyNumberFormats" type="xsd:boolean"/> + <xsd:attribute name="applyBorderFormats" type="xsd:boolean"/> + <xsd:attribute name="applyFontFormats" type="xsd:boolean"/> + <xsd:attribute name="applyPatternFormats" type="xsd:boolean"/> + <xsd:attribute name="applyAlignmentFormats" type="xsd:boolean"/> + <xsd:attribute name="applyWidthHeightFormats" type="xsd:boolean"/> + </xsd:attributeGroup> + <xsd:element name="externalLink" type="CT_ExternalLink"/> + <xsd:complexType name="CT_ExternalLink"> + <xsd:sequence> + <xsd:choice> + <xsd:element name="externalBook" type="CT_ExternalBook" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ddeLink" type="CT_DdeLink" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oleLink" type="CT_OleLink" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExternalBook"> + <xsd:sequence> + <xsd:element name="sheetNames" type="CT_ExternalSheetNames" minOccurs="0" maxOccurs="1"/> + <xsd:element name="definedNames" type="CT_ExternalDefinedNames" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheetDataSet" type="CT_ExternalSheetDataSet" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ExternalSheetNames"> + <xsd:sequence> + <xsd:element name="sheetName" minOccurs="1" maxOccurs="unbounded" type="CT_ExternalSheetName" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExternalSheetName"> + <xsd:attribute name="val" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_ExternalDefinedNames"> + <xsd:sequence> + <xsd:element name="definedName" type="CT_ExternalDefinedName" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExternalDefinedName"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="refersTo" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_ExternalSheetDataSet"> + <xsd:sequence> + <xsd:element name="sheetData" type="CT_ExternalSheetData" minOccurs="1" maxOccurs="unbounded" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExternalSheetData"> + <xsd:sequence> + <xsd:element name="row" type="CT_ExternalRow" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="refreshError" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_ExternalRow"> + <xsd:sequence> + <xsd:element name="cell" type="CT_ExternalCell" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="r" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_ExternalCell"> + <xsd:sequence> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="r" type="ST_CellRef" use="optional"/> + <xsd:attribute name="t" type="ST_CellType" use="optional" default="n"/> + <xsd:attribute name="vm" type="xsd:unsignedInt" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_DdeLink"> + <xsd:sequence> + <xsd:element name="ddeItems" type="CT_DdeItems" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ddeService" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="ddeTopic" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DdeItems"> + <xsd:sequence> + <xsd:element name="ddeItem" type="CT_DdeItem" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DdeItem"> + <xsd:sequence> + <xsd:element name="values" type="CT_DdeValues" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" default="0"/> + <xsd:attribute name="ole" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="advise" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="preferPic" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_DdeValues"> + <xsd:sequence> + <xsd:element name="value" minOccurs="1" maxOccurs="unbounded" type="CT_DdeValue"/> + </xsd:sequence> + <xsd:attribute name="rows" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="cols" type="xsd:unsignedInt" use="optional" default="1"/> + </xsd:complexType> + <xsd:complexType name="CT_DdeValue"> + <xsd:sequence> + <xsd:element name="val" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="t" type="ST_DdeValueType" use="optional" default="n"/> + </xsd:complexType> + <xsd:simpleType name="ST_DdeValueType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="nil"/> + <xsd:enumeration value="b"/> + <xsd:enumeration value="n"/> + <xsd:enumeration value="e"/> + <xsd:enumeration value="str"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_OleLink"> + <xsd:sequence> + <xsd:element name="oleItems" type="CT_OleItems" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="progId" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_OleItems"> + <xsd:sequence> + <xsd:element name="oleItem" type="CT_OleItem" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_OleItem"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="icon" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="advise" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="preferPic" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:element name="table" type="CT_Table"/> + <xsd:complexType name="CT_Table"> + <xsd:sequence> + <xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sortState" type="CT_SortState" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tableColumns" type="CT_TableColumns" minOccurs="1" maxOccurs="1"/> + <xsd:element name="tableStyleInfo" type="CT_TableStyleInfo" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="displayName" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="comment" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + <xsd:attribute name="tableType" type="ST_TableType" use="optional" default="worksheet"/> + <xsd:attribute name="headerRowCount" type="xsd:unsignedInt" use="optional" default="1"/> + <xsd:attribute name="insertRow" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="insertRowShift" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="totalsRowCount" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="totalsRowShown" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="published" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="headerRowDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="dataDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="totalsRowDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="headerRowBorderDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="tableBorderDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="totalsRowBorderDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="headerRowCellStyle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="dataCellStyle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="totalsRowCellStyle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="connectionId" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TableType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="worksheet"/> + <xsd:enumeration value="xml"/> + <xsd:enumeration value="queryTable"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TableStyleInfo"> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="showFirstColumn" type="xsd:boolean" use="optional"/> + <xsd:attribute name="showLastColumn" type="xsd:boolean" use="optional"/> + <xsd:attribute name="showRowStripes" type="xsd:boolean" use="optional"/> + <xsd:attribute name="showColumnStripes" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableColumns"> + <xsd:sequence> + <xsd:element name="tableColumn" type="CT_TableColumn" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableColumn"> + <xsd:sequence> + <xsd:element name="calculatedColumnFormula" type="CT_TableFormula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="totalsRowFormula" type="CT_TableFormula" minOccurs="0" maxOccurs="1"/> + <xsd:element name="xmlColumnPr" type="CT_XmlColumnPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="uniqueName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="totalsRowFunction" type="ST_TotalsRowFunction" use="optional" + default="none"/> + <xsd:attribute name="totalsRowLabel" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="queryTableFieldId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="headerRowDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="dataDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="totalsRowDxfId" type="ST_DxfId" use="optional"/> + <xsd:attribute name="headerRowCellStyle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="dataCellStyle" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="totalsRowCellStyle" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_TableFormula"> + <xsd:simpleContent> + <xsd:extension base="ST_Formula"> + <xsd:attribute name="array" type="xsd:boolean" default="false"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:simpleType name="ST_TotalsRowFunction"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="sum"/> + <xsd:enumeration value="min"/> + <xsd:enumeration value="max"/> + <xsd:enumeration value="average"/> + <xsd:enumeration value="count"/> + <xsd:enumeration value="countNums"/> + <xsd:enumeration value="stdDev"/> + <xsd:enumeration value="var"/> + <xsd:enumeration value="custom"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_XmlColumnPr"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="mapId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="xpath" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="denormalized" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="xmlDataType" type="ST_XmlDataType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_XmlDataType"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:element name="volTypes" type="CT_VolTypes"/> + <xsd:complexType name="CT_VolTypes"> + <xsd:sequence> + <xsd:element name="volType" type="CT_VolType" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_VolType"> + <xsd:sequence> + <xsd:element name="main" type="CT_VolMain" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_VolDepType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_VolMain"> + <xsd:sequence> + <xsd:element name="tp" type="CT_VolTopic" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="first" type="s:ST_Xstring" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_VolTopic"> + <xsd:sequence> + <xsd:element name="v" type="s:ST_Xstring" minOccurs="1" maxOccurs="1"/> + <xsd:element name="stp" type="s:ST_Xstring" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="tr" type="CT_VolTopicRef" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="t" type="ST_VolValueType" use="optional" default="n"/> + </xsd:complexType> + <xsd:complexType name="CT_VolTopicRef"> + <xsd:attribute name="r" type="ST_CellRef" use="required"/> + <xsd:attribute name="s" type="xsd:unsignedInt" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_VolDepType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="realTimeData"/> + <xsd:enumeration value="olapFunctions"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_VolValueType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="b"/> + <xsd:enumeration value="n"/> + <xsd:enumeration value="e"/> + <xsd:enumeration value="s"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:element name="workbook" type="CT_Workbook"/> + <xsd:complexType name="CT_Workbook"> + <xsd:sequence> + <xsd:element name="fileVersion" type="CT_FileVersion" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fileSharing" type="CT_FileSharing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="workbookPr" type="CT_WorkbookPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="workbookProtection" type="CT_WorkbookProtection" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="bookViews" type="CT_BookViews" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sheets" type="CT_Sheets" minOccurs="1" maxOccurs="1"/> + <xsd:element name="functionGroups" type="CT_FunctionGroups" minOccurs="0" maxOccurs="1"/> + <xsd:element name="externalReferences" type="CT_ExternalReferences" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="definedNames" type="CT_DefinedNames" minOccurs="0" maxOccurs="1"/> + <xsd:element name="calcPr" type="CT_CalcPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="oleSize" type="CT_OleSize" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customWorkbookViews" type="CT_CustomWorkbookViews" minOccurs="0" + maxOccurs="1"/> + <xsd:element name="pivotCaches" type="CT_PivotCaches" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smartTagPr" type="CT_SmartTagPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="smartTagTypes" type="CT_SmartTagTypes" minOccurs="0" maxOccurs="1"/> + <xsd:element name="webPublishing" type="CT_WebPublishing" minOccurs="0" maxOccurs="1"/> + <xsd:element name="fileRecoveryPr" type="CT_FileRecoveryPr" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="webPublishObjects" type="CT_WebPublishObjects" minOccurs="0" maxOccurs="1"/> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="conformance" type="s:ST_ConformanceClass"/> + </xsd:complexType> + <xsd:complexType name="CT_FileVersion"> + <xsd:attribute name="appName" type="xsd:string" use="optional"/> + <xsd:attribute name="lastEdited" type="xsd:string" use="optional"/> + <xsd:attribute name="lowestEdited" type="xsd:string" use="optional"/> + <xsd:attribute name="rupBuild" type="xsd:string" use="optional"/> + <xsd:attribute name="codeName" type="s:ST_Guid" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_BookViews"> + <xsd:sequence> + <xsd:element name="workbookView" type="CT_BookView" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_BookView"> + <xsd:sequence> + <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="visibility" type="ST_Visibility" use="optional" default="visible"/> + <xsd:attribute name="minimized" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showHorizontalScroll" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showVerticalScroll" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showSheetTabs" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="xWindow" type="xsd:int" use="optional"/> + <xsd:attribute name="yWindow" type="xsd:int" use="optional"/> + <xsd:attribute name="windowWidth" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="windowHeight" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="tabRatio" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="firstSheet" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="activeTab" type="xsd:unsignedInt" use="optional" default="0"/> + <xsd:attribute name="autoFilterDateGrouping" type="xsd:boolean" use="optional" default="true"/> + </xsd:complexType> + <xsd:simpleType name="ST_Visibility"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="visible"/> + <xsd:enumeration value="hidden"/> + <xsd:enumeration value="veryHidden"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_CustomWorkbookViews"> + <xsd:sequence> + <xsd:element name="customWorkbookView" minOccurs="1" maxOccurs="unbounded" + type="CT_CustomWorkbookView"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomWorkbookView"> + <xsd:sequence> + <xsd:element name="extLst" minOccurs="0" type="CT_ExtensionList"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="guid" type="s:ST_Guid" use="required"/> + <xsd:attribute name="autoUpdate" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="mergeInterval" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="changesSavedWin" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="onlySync" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="personalView" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="includePrintSettings" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="includeHiddenRowCol" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="maximized" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="minimized" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showHorizontalScroll" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showVerticalScroll" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showSheetTabs" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="xWindow" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="yWindow" type="xsd:int" use="optional" default="0"/> + <xsd:attribute name="windowWidth" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="windowHeight" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="tabRatio" type="xsd:unsignedInt" use="optional" default="600"/> + <xsd:attribute name="activeSheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="showFormulaBar" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showStatusbar" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="showComments" type="ST_Comments" use="optional" default="commIndicator"/> + <xsd:attribute name="showObjects" type="ST_Objects" use="optional" default="all"/> + </xsd:complexType> + <xsd:simpleType name="ST_Comments"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="commNone"/> + <xsd:enumeration value="commIndicator"/> + <xsd:enumeration value="commIndAndComment"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Objects"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="all"/> + <xsd:enumeration value="placeholders"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Sheets"> + <xsd:sequence> + <xsd:element name="sheet" type="CT_Sheet" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Sheet"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="sheetId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="state" type="ST_SheetState" use="optional" default="visible"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_SheetState"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="visible"/> + <xsd:enumeration value="hidden"/> + <xsd:enumeration value="veryHidden"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_WorkbookPr"> + <xsd:attribute name="date1904" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showObjects" type="ST_Objects" use="optional" default="all"/> + <xsd:attribute name="showBorderUnselectedTables" type="xsd:boolean" use="optional" + default="true"/> + <xsd:attribute name="filterPrivacy" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="promptedSolutions" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showInkAnnotation" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="backupFile" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="saveExternalLinkValues" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="updateLinks" type="ST_UpdateLinks" use="optional" default="userSet"/> + <xsd:attribute name="codeName" type="xsd:string" use="optional"/> + <xsd:attribute name="hidePivotFieldList" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="showPivotChartFilter" type="xsd:boolean" default="false"/> + <xsd:attribute name="allowRefreshQuery" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="publishItems" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="checkCompatibility" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="autoCompressPictures" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="refreshAllConnections" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="defaultThemeVersion" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_UpdateLinks"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="userSet"/> + <xsd:enumeration value="never"/> + <xsd:enumeration value="always"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SmartTagPr"> + <xsd:attribute name="embed" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="show" type="ST_SmartTagShow" use="optional" default="all"/> + </xsd:complexType> + <xsd:simpleType name="ST_SmartTagShow"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="all"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="noIndicator"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SmartTagTypes"> + <xsd:sequence> + <xsd:element name="smartTagType" type="CT_SmartTagType" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SmartTagType"> + <xsd:attribute name="namespaceUri" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="name" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="url" type="s:ST_Xstring" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_FileRecoveryPr"> + <xsd:attribute name="autoRecover" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="crashSave" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="dataExtractLoad" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="repairLoad" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> + <xsd:complexType name="CT_CalcPr"> + <xsd:attribute name="calcId" type="xsd:unsignedInt"/> + <xsd:attribute name="calcMode" type="ST_CalcMode" use="optional" default="auto"/> + <xsd:attribute name="fullCalcOnLoad" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="refMode" type="ST_RefMode" use="optional" default="A1"/> + <xsd:attribute name="iterate" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="iterateCount" type="xsd:unsignedInt" use="optional" default="100"/> + <xsd:attribute name="iterateDelta" type="xsd:double" use="optional" default="0.001"/> + <xsd:attribute name="fullPrecision" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="calcCompleted" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="calcOnSave" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="concurrentCalc" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="concurrentManualCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="forceFullCalc" type="xsd:boolean" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_CalcMode"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="manual"/> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="autoNoTable"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_RefMode"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="A1"/> + <xsd:enumeration value="R1C1"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DefinedNames"> + <xsd:sequence> + <xsd:element name="definedName" type="CT_DefinedName" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DefinedName"> + <xsd:simpleContent> + <xsd:extension base="ST_Formula"> + <xsd:attribute name="name" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="comment" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="customMenu" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="description" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="help" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="statusBar" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="localSheetId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="hidden" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="function" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="vbProcedure" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="xlm" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="functionGroupId" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="shortcutKey" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="publishToServer" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="workbookParameter" type="xsd:boolean" use="optional" default="false"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:complexType name="CT_ExternalReferences"> + <xsd:sequence> + <xsd:element name="externalReference" type="CT_ExternalReference" minOccurs="1" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ExternalReference"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SheetBackgroundPicture"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PivotCaches"> + <xsd:sequence> + <xsd:element name="pivotCache" type="CT_PivotCache" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PivotCache"> + <xsd:attribute name="cacheId" type="xsd:unsignedInt" use="required"/> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FileSharing"> + <xsd:attribute name="readOnlyRecommended" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="userName" type="s:ST_Xstring"/> + <xsd:attribute name="reservationPassword" type="ST_UnsignedShortHex"/> + <xsd:attribute name="algorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinCount" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_OleSize"> + <xsd:attribute name="ref" type="ST_Ref" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_WorkbookProtection"> + <xsd:attribute name="workbookPassword" type="ST_UnsignedShortHex" use="optional"/> + <xsd:attribute name="workbookPasswordCharacterSet" type="xsd:string" use="optional"/> + <xsd:attribute name="revisionsPassword" type="ST_UnsignedShortHex" use="optional"/> + <xsd:attribute name="revisionsPasswordCharacterSet" type="xsd:string" use="optional"/> + <xsd:attribute name="lockStructure" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="lockWindows" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="lockRevision" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="revisionsAlgorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="revisionsHashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="revisionsSaltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="revisionsSpinCount" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="workbookAlgorithmName" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="workbookHashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="workbookSaltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="workbookSpinCount" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_WebPublishing"> + <xsd:attribute name="css" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="thicket" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="longFileNames" type="xsd:boolean" use="optional" default="true"/> + <xsd:attribute name="vml" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="allowPng" type="xsd:boolean" use="optional" default="false"/> + <xsd:attribute name="targetScreenSize" type="ST_TargetScreenSize" use="optional" + default="800x600"/> + <xsd:attribute name="dpi" type="xsd:unsignedInt" use="optional" default="96"/> + <xsd:attribute name="codePage" type="xsd:unsignedInt" use="optional"/> + <xsd:attribute name="characterSet" type="xsd:string" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TargetScreenSize"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="544x376"/> + <xsd:enumeration value="640x480"/> + <xsd:enumeration value="720x512"/> + <xsd:enumeration value="800x600"/> + <xsd:enumeration value="1024x768"/> + <xsd:enumeration value="1152x882"/> + <xsd:enumeration value="1152x900"/> + <xsd:enumeration value="1280x1024"/> + <xsd:enumeration value="1600x1200"/> + <xsd:enumeration value="1800x1440"/> + <xsd:enumeration value="1920x1200"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FunctionGroups"> + <xsd:sequence maxOccurs="unbounded"> + <xsd:element name="functionGroup" type="CT_FunctionGroup" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="builtInGroupCount" type="xsd:unsignedInt" default="16" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_FunctionGroup"> + <xsd:attribute name="name" type="s:ST_Xstring"/> + </xsd:complexType> + <xsd:complexType name="CT_WebPublishObjects"> + <xsd:sequence> + <xsd:element name="webPublishObject" type="CT_WebPublishObject" minOccurs="1" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="count" type="xsd:unsignedInt" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_WebPublishObject"> + <xsd:attribute name="id" type="xsd:unsignedInt" use="required"/> + <xsd:attribute name="divId" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="sourceObject" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="destinationFile" type="s:ST_Xstring" use="required"/> + <xsd:attribute name="title" type="s:ST_Xstring" use="optional"/> + <xsd:attribute name="autoRepublish" type="xsd:boolean" use="optional" default="false"/> + </xsd:complexType> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd new file mode 100644 index 0000000..8821dd1 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd new file mode 100644 index 0000000..ca2575c --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd new file mode 100644 index 0000000..dd079e6 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd new file mode 100644 index 0000000..3dd6cf6 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd new file mode 100644 index 0000000..f1041e3 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd new file mode 100644 index 0000000..9c5b7a6 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd @@ -0,0 +1,3646 @@ +<?xml version="1.0" encoding="utf-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" + xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" + xmlns="http://schemas.openxmlformats.org/wordprocessingml/2006/main" + xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" + targetNamespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> + <xsd:import namespace="http://schemas.openxmlformats.org/markup-compatibility/2006" schemaLocation="../mce/mc.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" + schemaLocation="dml-wordprocessingDrawing.xsd"/> + <xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/math" + schemaLocation="shared-math.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:import namespace="http://schemas.openxmlformats.org/schemaLibrary/2006/main" + schemaLocation="shared-customXmlSchemaProperties.xsd"/> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> + <xsd:complexType name="CT_Empty"/> + <xsd:complexType name="CT_OnOff"> + <xsd:attribute name="val" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:simpleType name="ST_LongHexNumber"> + <xsd:restriction base="xsd:hexBinary"> + <xsd:length value="4"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LongHexNumber"> + <xsd:attribute name="val" type="ST_LongHexNumber" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_ShortHexNumber"> + <xsd:restriction base="xsd:hexBinary"> + <xsd:length value="2"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_UcharHexNumber"> + <xsd:restriction base="xsd:hexBinary"> + <xsd:length value="1"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Charset"> + <xsd:attribute name="val" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="characterSet" type="s:ST_String" use="optional" default="ISO-8859-1"/> + </xsd:complexType> + <xsd:simpleType name="ST_DecimalNumberOrPercent"> + <xsd:union memberTypes="ST_UnqualifiedPercentage s:ST_Percentage"/> + </xsd:simpleType> + <xsd:simpleType name="ST_UnqualifiedPercentage"> + <xsd:restriction base="xsd:decimal"/> + </xsd:simpleType> + <xsd:simpleType name="ST_DecimalNumber"> + <xsd:restriction base="xsd:integer"/> + </xsd:simpleType> + <xsd:complexType name="CT_DecimalNumber"> + <xsd:attribute name="val" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_UnsignedDecimalNumber"> + <xsd:attribute name="val" type="s:ST_UnsignedDecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DecimalNumberOrPrecent"> + <xsd:attribute name="val" type="ST_DecimalNumberOrPercent" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TwipsMeasure"> + <xsd:attribute name="val" type="s:ST_TwipsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_SignedTwipsMeasure"> + <xsd:union memberTypes="xsd:integer s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:complexType name="CT_SignedTwipsMeasure"> + <xsd:attribute name="val" type="ST_SignedTwipsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PixelsMeasure"> + <xsd:restriction base="s:ST_UnsignedDecimalNumber"/> + </xsd:simpleType> + <xsd:complexType name="CT_PixelsMeasure"> + <xsd:attribute name="val" type="ST_PixelsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_HpsMeasure"> + <xsd:union memberTypes="s:ST_UnsignedDecimalNumber s:ST_PositiveUniversalMeasure"/> + </xsd:simpleType> + <xsd:complexType name="CT_HpsMeasure"> + <xsd:attribute name="val" type="ST_HpsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_SignedHpsMeasure"> + <xsd:union memberTypes="xsd:integer s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:complexType name="CT_SignedHpsMeasure"> + <xsd:attribute name="val" type="ST_SignedHpsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DateTime"> + <xsd:restriction base="xsd:dateTime"/> + </xsd:simpleType> + <xsd:simpleType name="ST_MacroName"> + <xsd:restriction base="xsd:string"> + <xsd:maxLength value="33"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MacroName"> + <xsd:attribute name="val" use="required" type="ST_MacroName"/> + </xsd:complexType> + <xsd:simpleType name="ST_EighthPointMeasure"> + <xsd:restriction base="s:ST_UnsignedDecimalNumber"/> + </xsd:simpleType> + <xsd:simpleType name="ST_PointMeasure"> + <xsd:restriction base="s:ST_UnsignedDecimalNumber"/> + </xsd:simpleType> + <xsd:complexType name="CT_String"> + <xsd:attribute name="val" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextScale"> + <xsd:union memberTypes="ST_TextScalePercent ST_TextScaleDecimal"/> + </xsd:simpleType> + <xsd:simpleType name="ST_TextScalePercent"> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="0*(600|([0-5]?[0-9]?[0-9]))%"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TextScaleDecimal"> + <xsd:restriction base="xsd:integer"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="600"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextScale"> + <xsd:attribute name="val" type="ST_TextScale"/> + </xsd:complexType> + <xsd:simpleType name="ST_HighlightColor"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="black"/> + <xsd:enumeration value="blue"/> + <xsd:enumeration value="cyan"/> + <xsd:enumeration value="green"/> + <xsd:enumeration value="magenta"/> + <xsd:enumeration value="red"/> + <xsd:enumeration value="yellow"/> + <xsd:enumeration value="white"/> + <xsd:enumeration value="darkBlue"/> + <xsd:enumeration value="darkCyan"/> + <xsd:enumeration value="darkGreen"/> + <xsd:enumeration value="darkMagenta"/> + <xsd:enumeration value="darkRed"/> + <xsd:enumeration value="darkYellow"/> + <xsd:enumeration value="darkGray"/> + <xsd:enumeration value="lightGray"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Highlight"> + <xsd:attribute name="val" type="ST_HighlightColor" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_HexColorAuto"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HexColor"> + <xsd:union memberTypes="ST_HexColorAuto s:ST_HexColorRGB"/> + </xsd:simpleType> + <xsd:complexType name="CT_Color"> + <xsd:attribute name="val" type="ST_HexColor" use="required"/> + <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Lang"> + <xsd:attribute name="val" type="s:ST_Lang" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Guid"> + <xsd:attribute name="val" type="s:ST_Guid"/> + </xsd:complexType> + <xsd:simpleType name="ST_Underline"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="single"/> + <xsd:enumeration value="words"/> + <xsd:enumeration value="double"/> + <xsd:enumeration value="thick"/> + <xsd:enumeration value="dotted"/> + <xsd:enumeration value="dottedHeavy"/> + <xsd:enumeration value="dash"/> + <xsd:enumeration value="dashedHeavy"/> + <xsd:enumeration value="dashLong"/> + <xsd:enumeration value="dashLongHeavy"/> + <xsd:enumeration value="dotDash"/> + <xsd:enumeration value="dashDotHeavy"/> + <xsd:enumeration value="dotDotDash"/> + <xsd:enumeration value="dashDotDotHeavy"/> + <xsd:enumeration value="wave"/> + <xsd:enumeration value="wavyHeavy"/> + <xsd:enumeration value="wavyDouble"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Underline"> + <xsd:attribute name="val" type="ST_Underline" use="optional"/> + <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/> + <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextEffect"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="blinkBackground"/> + <xsd:enumeration value="lights"/> + <xsd:enumeration value="antsBlack"/> + <xsd:enumeration value="antsRed"/> + <xsd:enumeration value="shimmer"/> + <xsd:enumeration value="sparkle"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextEffect"> + <xsd:attribute name="val" type="ST_TextEffect" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Border"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="nil"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="single"/> + <xsd:enumeration value="thick"/> + <xsd:enumeration value="double"/> + <xsd:enumeration value="dotted"/> + <xsd:enumeration value="dashed"/> + <xsd:enumeration value="dotDash"/> + <xsd:enumeration value="dotDotDash"/> + <xsd:enumeration value="triple"/> + <xsd:enumeration value="thinThickSmallGap"/> + <xsd:enumeration value="thickThinSmallGap"/> + <xsd:enumeration value="thinThickThinSmallGap"/> + <xsd:enumeration value="thinThickMediumGap"/> + <xsd:enumeration value="thickThinMediumGap"/> + <xsd:enumeration value="thinThickThinMediumGap"/> + <xsd:enumeration value="thinThickLargeGap"/> + <xsd:enumeration value="thickThinLargeGap"/> + <xsd:enumeration value="thinThickThinLargeGap"/> + <xsd:enumeration value="wave"/> + <xsd:enumeration value="doubleWave"/> + <xsd:enumeration value="dashSmallGap"/> + <xsd:enumeration value="dashDotStroked"/> + <xsd:enumeration value="threeDEmboss"/> + <xsd:enumeration value="threeDEngrave"/> + <xsd:enumeration value="outset"/> + <xsd:enumeration value="inset"/> + <xsd:enumeration value="apples"/> + <xsd:enumeration value="archedScallops"/> + <xsd:enumeration value="babyPacifier"/> + <xsd:enumeration value="babyRattle"/> + <xsd:enumeration value="balloons3Colors"/> + <xsd:enumeration value="balloonsHotAir"/> + <xsd:enumeration value="basicBlackDashes"/> + <xsd:enumeration value="basicBlackDots"/> + <xsd:enumeration value="basicBlackSquares"/> + <xsd:enumeration value="basicThinLines"/> + <xsd:enumeration value="basicWhiteDashes"/> + <xsd:enumeration value="basicWhiteDots"/> + <xsd:enumeration value="basicWhiteSquares"/> + <xsd:enumeration value="basicWideInline"/> + <xsd:enumeration value="basicWideMidline"/> + <xsd:enumeration value="basicWideOutline"/> + <xsd:enumeration value="bats"/> + <xsd:enumeration value="birds"/> + <xsd:enumeration value="birdsFlight"/> + <xsd:enumeration value="cabins"/> + <xsd:enumeration value="cakeSlice"/> + <xsd:enumeration value="candyCorn"/> + <xsd:enumeration value="celticKnotwork"/> + <xsd:enumeration value="certificateBanner"/> + <xsd:enumeration value="chainLink"/> + <xsd:enumeration value="champagneBottle"/> + <xsd:enumeration value="checkedBarBlack"/> + <xsd:enumeration value="checkedBarColor"/> + <xsd:enumeration value="checkered"/> + <xsd:enumeration value="christmasTree"/> + <xsd:enumeration value="circlesLines"/> + <xsd:enumeration value="circlesRectangles"/> + <xsd:enumeration value="classicalWave"/> + <xsd:enumeration value="clocks"/> + <xsd:enumeration value="compass"/> + <xsd:enumeration value="confetti"/> + <xsd:enumeration value="confettiGrays"/> + <xsd:enumeration value="confettiOutline"/> + <xsd:enumeration value="confettiStreamers"/> + <xsd:enumeration value="confettiWhite"/> + <xsd:enumeration value="cornerTriangles"/> + <xsd:enumeration value="couponCutoutDashes"/> + <xsd:enumeration value="couponCutoutDots"/> + <xsd:enumeration value="crazyMaze"/> + <xsd:enumeration value="creaturesButterfly"/> + <xsd:enumeration value="creaturesFish"/> + <xsd:enumeration value="creaturesInsects"/> + <xsd:enumeration value="creaturesLadyBug"/> + <xsd:enumeration value="crossStitch"/> + <xsd:enumeration value="cup"/> + <xsd:enumeration value="decoArch"/> + <xsd:enumeration value="decoArchColor"/> + <xsd:enumeration value="decoBlocks"/> + <xsd:enumeration value="diamondsGray"/> + <xsd:enumeration value="doubleD"/> + <xsd:enumeration value="doubleDiamonds"/> + <xsd:enumeration value="earth1"/> + <xsd:enumeration value="earth2"/> + <xsd:enumeration value="earth3"/> + <xsd:enumeration value="eclipsingSquares1"/> + <xsd:enumeration value="eclipsingSquares2"/> + <xsd:enumeration value="eggsBlack"/> + <xsd:enumeration value="fans"/> + <xsd:enumeration value="film"/> + <xsd:enumeration value="firecrackers"/> + <xsd:enumeration value="flowersBlockPrint"/> + <xsd:enumeration value="flowersDaisies"/> + <xsd:enumeration value="flowersModern1"/> + <xsd:enumeration value="flowersModern2"/> + <xsd:enumeration value="flowersPansy"/> + <xsd:enumeration value="flowersRedRose"/> + <xsd:enumeration value="flowersRoses"/> + <xsd:enumeration value="flowersTeacup"/> + <xsd:enumeration value="flowersTiny"/> + <xsd:enumeration value="gems"/> + <xsd:enumeration value="gingerbreadMan"/> + <xsd:enumeration value="gradient"/> + <xsd:enumeration value="handmade1"/> + <xsd:enumeration value="handmade2"/> + <xsd:enumeration value="heartBalloon"/> + <xsd:enumeration value="heartGray"/> + <xsd:enumeration value="hearts"/> + <xsd:enumeration value="heebieJeebies"/> + <xsd:enumeration value="holly"/> + <xsd:enumeration value="houseFunky"/> + <xsd:enumeration value="hypnotic"/> + <xsd:enumeration value="iceCreamCones"/> + <xsd:enumeration value="lightBulb"/> + <xsd:enumeration value="lightning1"/> + <xsd:enumeration value="lightning2"/> + <xsd:enumeration value="mapPins"/> + <xsd:enumeration value="mapleLeaf"/> + <xsd:enumeration value="mapleMuffins"/> + <xsd:enumeration value="marquee"/> + <xsd:enumeration value="marqueeToothed"/> + <xsd:enumeration value="moons"/> + <xsd:enumeration value="mosaic"/> + <xsd:enumeration value="musicNotes"/> + <xsd:enumeration value="northwest"/> + <xsd:enumeration value="ovals"/> + <xsd:enumeration value="packages"/> + <xsd:enumeration value="palmsBlack"/> + <xsd:enumeration value="palmsColor"/> + <xsd:enumeration value="paperClips"/> + <xsd:enumeration value="papyrus"/> + <xsd:enumeration value="partyFavor"/> + <xsd:enumeration value="partyGlass"/> + <xsd:enumeration value="pencils"/> + <xsd:enumeration value="people"/> + <xsd:enumeration value="peopleWaving"/> + <xsd:enumeration value="peopleHats"/> + <xsd:enumeration value="poinsettias"/> + <xsd:enumeration value="postageStamp"/> + <xsd:enumeration value="pumpkin1"/> + <xsd:enumeration value="pushPinNote2"/> + <xsd:enumeration value="pushPinNote1"/> + <xsd:enumeration value="pyramids"/> + <xsd:enumeration value="pyramidsAbove"/> + <xsd:enumeration value="quadrants"/> + <xsd:enumeration value="rings"/> + <xsd:enumeration value="safari"/> + <xsd:enumeration value="sawtooth"/> + <xsd:enumeration value="sawtoothGray"/> + <xsd:enumeration value="scaredCat"/> + <xsd:enumeration value="seattle"/> + <xsd:enumeration value="shadowedSquares"/> + <xsd:enumeration value="sharksTeeth"/> + <xsd:enumeration value="shorebirdTracks"/> + <xsd:enumeration value="skyrocket"/> + <xsd:enumeration value="snowflakeFancy"/> + <xsd:enumeration value="snowflakes"/> + <xsd:enumeration value="sombrero"/> + <xsd:enumeration value="southwest"/> + <xsd:enumeration value="stars"/> + <xsd:enumeration value="starsTop"/> + <xsd:enumeration value="stars3d"/> + <xsd:enumeration value="starsBlack"/> + <xsd:enumeration value="starsShadowed"/> + <xsd:enumeration value="sun"/> + <xsd:enumeration value="swirligig"/> + <xsd:enumeration value="tornPaper"/> + <xsd:enumeration value="tornPaperBlack"/> + <xsd:enumeration value="trees"/> + <xsd:enumeration value="triangleParty"/> + <xsd:enumeration value="triangles"/> + <xsd:enumeration value="triangle1"/> + <xsd:enumeration value="triangle2"/> + <xsd:enumeration value="triangleCircle1"/> + <xsd:enumeration value="triangleCircle2"/> + <xsd:enumeration value="shapes1"/> + <xsd:enumeration value="shapes2"/> + <xsd:enumeration value="twistedLines1"/> + <xsd:enumeration value="twistedLines2"/> + <xsd:enumeration value="vine"/> + <xsd:enumeration value="waveline"/> + <xsd:enumeration value="weavingAngles"/> + <xsd:enumeration value="weavingBraid"/> + <xsd:enumeration value="weavingRibbon"/> + <xsd:enumeration value="weavingStrips"/> + <xsd:enumeration value="whiteFlowers"/> + <xsd:enumeration value="woodwork"/> + <xsd:enumeration value="xIllusions"/> + <xsd:enumeration value="zanyTriangles"/> + <xsd:enumeration value="zigZag"/> + <xsd:enumeration value="zigZagStitch"/> + <xsd:enumeration value="custom"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Border"> + <xsd:attribute name="val" type="ST_Border" use="required"/> + <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/> + <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="sz" type="ST_EighthPointMeasure" use="optional"/> + <xsd:attribute name="space" type="ST_PointMeasure" use="optional" default="0"/> + <xsd:attribute name="shadow" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="frame" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Shd"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="nil"/> + <xsd:enumeration value="clear"/> + <xsd:enumeration value="solid"/> + <xsd:enumeration value="horzStripe"/> + <xsd:enumeration value="vertStripe"/> + <xsd:enumeration value="reverseDiagStripe"/> + <xsd:enumeration value="diagStripe"/> + <xsd:enumeration value="horzCross"/> + <xsd:enumeration value="diagCross"/> + <xsd:enumeration value="thinHorzStripe"/> + <xsd:enumeration value="thinVertStripe"/> + <xsd:enumeration value="thinReverseDiagStripe"/> + <xsd:enumeration value="thinDiagStripe"/> + <xsd:enumeration value="thinHorzCross"/> + <xsd:enumeration value="thinDiagCross"/> + <xsd:enumeration value="pct5"/> + <xsd:enumeration value="pct10"/> + <xsd:enumeration value="pct12"/> + <xsd:enumeration value="pct15"/> + <xsd:enumeration value="pct20"/> + <xsd:enumeration value="pct25"/> + <xsd:enumeration value="pct30"/> + <xsd:enumeration value="pct35"/> + <xsd:enumeration value="pct37"/> + <xsd:enumeration value="pct40"/> + <xsd:enumeration value="pct45"/> + <xsd:enumeration value="pct50"/> + <xsd:enumeration value="pct55"/> + <xsd:enumeration value="pct60"/> + <xsd:enumeration value="pct62"/> + <xsd:enumeration value="pct65"/> + <xsd:enumeration value="pct70"/> + <xsd:enumeration value="pct75"/> + <xsd:enumeration value="pct80"/> + <xsd:enumeration value="pct85"/> + <xsd:enumeration value="pct87"/> + <xsd:enumeration value="pct90"/> + <xsd:enumeration value="pct95"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Shd"> + <xsd:attribute name="val" type="ST_Shd" use="required"/> + <xsd:attribute name="color" type="ST_HexColor" use="optional"/> + <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="fill" type="ST_HexColor" use="optional"/> + <xsd:attribute name="themeFill" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeFillTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeFillShade" type="ST_UcharHexNumber" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_VerticalAlignRun"> + <xsd:attribute name="val" type="s:ST_VerticalAlignRun" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FitText"> + <xsd:attribute name="val" type="s:ST_TwipsMeasure" use="required"/> + <xsd:attribute name="id" type="ST_DecimalNumber" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Em"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="dot"/> + <xsd:enumeration value="comma"/> + <xsd:enumeration value="circle"/> + <xsd:enumeration value="underDot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Em"> + <xsd:attribute name="val" type="ST_Em" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Language"> + <xsd:attribute name="val" type="s:ST_Lang" use="optional"/> + <xsd:attribute name="eastAsia" type="s:ST_Lang" use="optional"/> + <xsd:attribute name="bidi" type="s:ST_Lang" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_CombineBrackets"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="round"/> + <xsd:enumeration value="square"/> + <xsd:enumeration value="angle"/> + <xsd:enumeration value="curly"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_EastAsianLayout"> + <xsd:attribute name="id" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="combine" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="combineBrackets" type="ST_CombineBrackets" use="optional"/> + <xsd:attribute name="vert" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="vertCompress" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_HeightRule"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="exact"/> + <xsd:enumeration value="atLeast"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Wrap"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="notBeside"/> + <xsd:enumeration value="around"/> + <xsd:enumeration value="tight"/> + <xsd:enumeration value="through"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_VAnchor"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="text"/> + <xsd:enumeration value="margin"/> + <xsd:enumeration value="page"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_HAnchor"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="text"/> + <xsd:enumeration value="margin"/> + <xsd:enumeration value="page"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DropCap"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="drop"/> + <xsd:enumeration value="margin"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FramePr"> + <xsd:attribute name="dropCap" type="ST_DropCap" use="optional"/> + <xsd:attribute name="lines" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="w" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="h" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="vSpace" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="hSpace" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="wrap" type="ST_Wrap" use="optional"/> + <xsd:attribute name="hAnchor" type="ST_HAnchor" use="optional"/> + <xsd:attribute name="vAnchor" type="ST_VAnchor" use="optional"/> + <xsd:attribute name="x" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="xAlign" type="s:ST_XAlign" use="optional"/> + <xsd:attribute name="y" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="yAlign" type="s:ST_YAlign" use="optional"/> + <xsd:attribute name="hRule" type="ST_HeightRule" use="optional"/> + <xsd:attribute name="anchorLock" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_TabJc"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="clear"/> + <xsd:enumeration value="start"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="end"/> + <xsd:enumeration value="decimal"/> + <xsd:enumeration value="bar"/> + <xsd:enumeration value="num"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_TabTlc"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="dot"/> + <xsd:enumeration value="hyphen"/> + <xsd:enumeration value="underscore"/> + <xsd:enumeration value="heavy"/> + <xsd:enumeration value="middleDot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TabStop"> + <xsd:attribute name="val" type="ST_TabJc" use="required"/> + <xsd:attribute name="leader" type="ST_TabTlc" use="optional"/> + <xsd:attribute name="pos" type="ST_SignedTwipsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_LineSpacingRule"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="auto"/> + <xsd:enumeration value="exact"/> + <xsd:enumeration value="atLeast"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Spacing"> + <xsd:attribute name="before" type="s:ST_TwipsMeasure" use="optional" default="0"/> + <xsd:attribute name="beforeLines" type="ST_DecimalNumber" use="optional" default="0"/> + <xsd:attribute name="beforeAutospacing" type="s:ST_OnOff" use="optional" default="off"/> + <xsd:attribute name="after" type="s:ST_TwipsMeasure" use="optional" default="0"/> + <xsd:attribute name="afterLines" type="ST_DecimalNumber" use="optional" default="0"/> + <xsd:attribute name="afterAutospacing" type="s:ST_OnOff" use="optional" default="off"/> + <xsd:attribute name="line" type="ST_SignedTwipsMeasure" use="optional" default="0"/> + <xsd:attribute name="lineRule" type="ST_LineSpacingRule" use="optional" default="auto"/> + </xsd:complexType> + <xsd:complexType name="CT_Ind"> + <xsd:attribute name="start" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="startChars" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="end" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="endChars" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="left" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="leftChars" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="right" type="ST_SignedTwipsMeasure" use="optional"/> + <xsd:attribute name="rightChars" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="hanging" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="hangingChars" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="firstLine" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="firstLineChars" type="ST_DecimalNumber" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Jc"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="start"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="end"/> + <xsd:enumeration value="both"/> + <xsd:enumeration value="mediumKashida"/> + <xsd:enumeration value="distribute"/> + <xsd:enumeration value="numTab"/> + <xsd:enumeration value="highKashida"/> + <xsd:enumeration value="lowKashida"/> + <xsd:enumeration value="thaiDistribute"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_JcTable"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="center"/> + <xsd:enumeration value="end"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + <xsd:enumeration value="start"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Jc"> + <xsd:attribute name="val" type="ST_Jc" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_JcTable"> + <xsd:attribute name="val" type="ST_JcTable" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_View"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="print"/> + <xsd:enumeration value="outline"/> + <xsd:enumeration value="masterPages"/> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="web"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_View"> + <xsd:attribute name="val" type="ST_View" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Zoom"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="fullPage"/> + <xsd:enumeration value="bestFit"/> + <xsd:enumeration value="textFit"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Zoom"> + <xsd:attribute name="val" type="ST_Zoom" use="optional"/> + <xsd:attribute name="percent" type="ST_DecimalNumberOrPercent" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_WritingStyle"> + <xsd:attribute name="lang" type="s:ST_Lang" use="required"/> + <xsd:attribute name="vendorID" type="s:ST_String" use="required"/> + <xsd:attribute name="dllVersion" type="s:ST_String" use="required"/> + <xsd:attribute name="nlCheck" type="s:ST_OnOff" use="optional" default="off"/> + <xsd:attribute name="checkStyle" type="s:ST_OnOff" use="required"/> + <xsd:attribute name="appName" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Proof"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="clean"/> + <xsd:enumeration value="dirty"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Proof"> + <xsd:attribute name="spelling" type="ST_Proof" use="optional"/> + <xsd:attribute name="grammar" type="ST_Proof" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_DocType"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:complexType name="CT_DocType"> + <xsd:attribute name="val" type="ST_DocType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DocProtect"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="readOnly"/> + <xsd:enumeration value="comments"/> + <xsd:enumeration value="trackedChanges"/> + <xsd:enumeration value="forms"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:attributeGroup name="AG_Password"> + <xsd:attribute name="algorithmName" type="s:ST_String" use="optional"/> + <xsd:attribute name="hashValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="saltValue" type="xsd:base64Binary" use="optional"/> + <xsd:attribute name="spinCount" type="ST_DecimalNumber" use="optional"/> + </xsd:attributeGroup> + <xsd:attributeGroup name="AG_TransitionalPassword"> + <xsd:attribute name="cryptProviderType" type="s:ST_CryptProv"/> + <xsd:attribute name="cryptAlgorithmClass" type="s:ST_AlgClass"/> + <xsd:attribute name="cryptAlgorithmType" type="s:ST_AlgType"/> + <xsd:attribute name="cryptAlgorithmSid" type="ST_DecimalNumber"/> + <xsd:attribute name="cryptSpinCount" type="ST_DecimalNumber"/> + <xsd:attribute name="cryptProvider" type="s:ST_String"/> + <xsd:attribute name="algIdExt" type="ST_LongHexNumber"/> + <xsd:attribute name="algIdExtSource" type="s:ST_String"/> + <xsd:attribute name="cryptProviderTypeExt" type="ST_LongHexNumber"/> + <xsd:attribute name="cryptProviderTypeExtSource" type="s:ST_String"/> + <xsd:attribute name="hash" type="xsd:base64Binary"/> + <xsd:attribute name="salt" type="xsd:base64Binary"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_DocProtect"> + <xsd:attribute name="edit" type="ST_DocProtect" use="optional"/> + <xsd:attribute name="formatting" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="enforcement" type="s:ST_OnOff"/> + <xsd:attributeGroup ref="AG_Password"/> + <xsd:attributeGroup ref="AG_TransitionalPassword"/> + </xsd:complexType> + <xsd:simpleType name="ST_MailMergeDocType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="catalog"/> + <xsd:enumeration value="envelopes"/> + <xsd:enumeration value="mailingLabels"/> + <xsd:enumeration value="formLetters"/> + <xsd:enumeration value="email"/> + <xsd:enumeration value="fax"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MailMergeDocType"> + <xsd:attribute name="val" type="ST_MailMergeDocType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MailMergeDataType"> + <xsd:restriction base="xsd:string"/> + </xsd:simpleType> + <xsd:complexType name="CT_MailMergeDataType"> + <xsd:attribute name="val" type="ST_MailMergeDataType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MailMergeDest"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="newDocument"/> + <xsd:enumeration value="printer"/> + <xsd:enumeration value="email"/> + <xsd:enumeration value="fax"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MailMergeDest"> + <xsd:attribute name="val" type="ST_MailMergeDest" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_MailMergeOdsoFMDFieldType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="null"/> + <xsd:enumeration value="dbColumn"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MailMergeOdsoFMDFieldType"> + <xsd:attribute name="val" type="ST_MailMergeOdsoFMDFieldType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TrackChangesView"> + <xsd:attribute name="markup" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="comments" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="insDel" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="formatting" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="inkAnnotations" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Kinsoku"> + <xsd:attribute name="lang" type="s:ST_Lang" use="required"/> + <xsd:attribute name="val" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextDirection"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="tb"/> + <xsd:enumeration value="rl"/> + <xsd:enumeration value="lr"/> + <xsd:enumeration value="tbV"/> + <xsd:enumeration value="rlV"/> + <xsd:enumeration value="lrV"/> + <xsd:enumeration value="btLr"/> + <xsd:enumeration value="lrTb"/> + <xsd:enumeration value="lrTbV"/> + <xsd:enumeration value="tbLrV"/> + <xsd:enumeration value="tbRl"/> + <xsd:enumeration value="tbRlV"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextDirection"> + <xsd:attribute name="val" type="ST_TextDirection" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_TextAlignment"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="top"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="baseline"/> + <xsd:enumeration value="bottom"/> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextAlignment"> + <xsd:attribute name="val" type="ST_TextAlignment" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DisplacedByCustomXml"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="next"/> + <xsd:enumeration value="prev"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_AnnotationVMerge"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="cont"/> + <xsd:enumeration value="rest"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Markup"> + <xsd:attribute name="id" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TrackChange"> + <xsd:complexContent> + <xsd:extension base="CT_Markup"> + <xsd:attribute name="author" type="s:ST_String" use="required"/> + <xsd:attribute name="date" type="ST_DateTime" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_CellMergeTrackChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:attribute name="vMerge" type="ST_AnnotationVMerge" use="optional"/> + <xsd:attribute name="vMergeOrig" type="ST_AnnotationVMerge" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TrackChangeRange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:attribute name="displacedByCustomXml" type="ST_DisplacedByCustomXml" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_MarkupRange"> + <xsd:complexContent> + <xsd:extension base="CT_Markup"> + <xsd:attribute name="displacedByCustomXml" type="ST_DisplacedByCustomXml" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_BookmarkRange"> + <xsd:complexContent> + <xsd:extension base="CT_MarkupRange"> + <xsd:attribute name="colFirst" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="colLast" type="ST_DecimalNumber" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Bookmark"> + <xsd:complexContent> + <xsd:extension base="CT_BookmarkRange"> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_MoveBookmark"> + <xsd:complexContent> + <xsd:extension base="CT_Bookmark"> + <xsd:attribute name="author" type="s:ST_String" use="required"/> + <xsd:attribute name="date" type="ST_DateTime" use="required"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Comment"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:group ref="EG_BlockLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="initials" type="s:ST_String" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TrackChangeNumbering"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:attribute name="original" type="s:ST_String" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TblPrExChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="tblPrEx" type="CT_TblPrExBase" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TcPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="tcPr" type="CT_TcPrInner" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TrPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="trPr" type="CT_TrPrBase" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TblGridChange"> + <xsd:complexContent> + <xsd:extension base="CT_Markup"> + <xsd:sequence> + <xsd:element name="tblGrid" type="CT_TblGridBase"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TblPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="tblPr" type="CT_TblPrBase"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_SectPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="sectPr" type="CT_SectPrBase" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_PPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="pPr" type="CT_PPrBase" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_RPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_RPrOriginal" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_ParaRPrChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_ParaRPrOriginal" minOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_RunTrackChange"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:group ref="EG_ContentRunContent"/> + <xsd:group ref="m:EG_OMathMathElements"/> + </xsd:choice> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:group name="EG_PContentMath"> + <xsd:choice> + <xsd:group ref="EG_PContentBase" minOccurs="0" maxOccurs="unbounded"/> + <xsd:group ref="EG_ContentRunContentBase" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_PContentBase"> + <xsd:choice> + <xsd:element name="customXml" type="CT_CustomXmlRun"/> + <xsd:element name="fldSimple" type="CT_SimpleField" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="hyperlink" type="CT_Hyperlink"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_ContentRunContentBase"> + <xsd:choice> + <xsd:element name="smartTag" type="CT_SmartTagRun"/> + <xsd:element name="sdt" type="CT_SdtRun"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_CellMarkupElements"> + <xsd:choice> + <xsd:element name="cellIns" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="cellDel" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="cellMerge" type="CT_CellMergeTrackChange" minOccurs="0"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_RangeMarkupElements"> + <xsd:choice> + <xsd:element name="bookmarkStart" type="CT_Bookmark"/> + <xsd:element name="bookmarkEnd" type="CT_MarkupRange"/> + <xsd:element name="moveFromRangeStart" type="CT_MoveBookmark"/> + <xsd:element name="moveFromRangeEnd" type="CT_MarkupRange"/> + <xsd:element name="moveToRangeStart" type="CT_MoveBookmark"/> + <xsd:element name="moveToRangeEnd" type="CT_MarkupRange"/> + <xsd:element name="commentRangeStart" type="CT_MarkupRange"/> + <xsd:element name="commentRangeEnd" type="CT_MarkupRange"/> + <xsd:element name="customXmlInsRangeStart" type="CT_TrackChange"/> + <xsd:element name="customXmlInsRangeEnd" type="CT_Markup"/> + <xsd:element name="customXmlDelRangeStart" type="CT_TrackChange"/> + <xsd:element name="customXmlDelRangeEnd" type="CT_Markup"/> + <xsd:element name="customXmlMoveFromRangeStart" type="CT_TrackChange"/> + <xsd:element name="customXmlMoveFromRangeEnd" type="CT_Markup"/> + <xsd:element name="customXmlMoveToRangeStart" type="CT_TrackChange"/> + <xsd:element name="customXmlMoveToRangeEnd" type="CT_Markup"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_NumPr"> + <xsd:sequence> + <xsd:element name="ilvl" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="numId" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0"/> + <xsd:element name="ins" type="CT_TrackChange" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PBdr"> + <xsd:sequence> + <xsd:element name="top" type="CT_Border" minOccurs="0"/> + <xsd:element name="left" type="CT_Border" minOccurs="0"/> + <xsd:element name="bottom" type="CT_Border" minOccurs="0"/> + <xsd:element name="right" type="CT_Border" minOccurs="0"/> + <xsd:element name="between" type="CT_Border" minOccurs="0"/> + <xsd:element name="bar" type="CT_Border" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Tabs"> + <xsd:sequence> + <xsd:element name="tab" type="CT_TabStop" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TextboxTightWrap"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="allLines"/> + <xsd:enumeration value="firstAndLastLine"/> + <xsd:enumeration value="firstLineOnly"/> + <xsd:enumeration value="lastLineOnly"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TextboxTightWrap"> + <xsd:attribute name="val" type="ST_TextboxTightWrap" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_PPrBase"> + <xsd:sequence> + <xsd:element name="pStyle" type="CT_String" minOccurs="0"/> + <xsd:element name="keepNext" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="keepLines" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="pageBreakBefore" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="framePr" type="CT_FramePr" minOccurs="0"/> + <xsd:element name="widowControl" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="numPr" type="CT_NumPr" minOccurs="0"/> + <xsd:element name="suppressLineNumbers" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="pBdr" type="CT_PBdr" minOccurs="0"/> + <xsd:element name="shd" type="CT_Shd" minOccurs="0"/> + <xsd:element name="tabs" type="CT_Tabs" minOccurs="0"/> + <xsd:element name="suppressAutoHyphens" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="kinsoku" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="wordWrap" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="overflowPunct" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="topLinePunct" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="autoSpaceDE" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="autoSpaceDN" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bidi" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="adjustRightInd" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="snapToGrid" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="spacing" type="CT_Spacing" minOccurs="0"/> + <xsd:element name="ind" type="CT_Ind" minOccurs="0"/> + <xsd:element name="contextualSpacing" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="mirrorIndents" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressOverlap" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="jc" type="CT_Jc" minOccurs="0"/> + <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0"/> + <xsd:element name="textAlignment" type="CT_TextAlignment" minOccurs="0"/> + <xsd:element name="textboxTightWrap" type="CT_TextboxTightWrap" minOccurs="0"/> + <xsd:element name="outlineLvl" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="divId" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="cnfStyle" type="CT_Cnf" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PPr"> + <xsd:complexContent> + <xsd:extension base="CT_PPrBase"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_ParaRPr" minOccurs="0"/> + <xsd:element name="sectPr" type="CT_SectPr" minOccurs="0"/> + <xsd:element name="pPrChange" type="CT_PPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_PPrGeneral"> + <xsd:complexContent> + <xsd:extension base="CT_PPrBase"> + <xsd:sequence> + <xsd:element name="pPrChange" type="CT_PPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Control"> + <xsd:attribute name="name" type="s:ST_String" use="optional"/> + <xsd:attribute name="shapeid" type="s:ST_String" use="optional"/> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Background"> + <xsd:sequence> + <xsd:sequence maxOccurs="unbounded"> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:vml" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:office:office" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:element name="drawing" type="CT_Drawing" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="color" type="ST_HexColor" use="optional" default="auto"/> + <xsd:attribute name="themeColor" type="ST_ThemeColor" use="optional"/> + <xsd:attribute name="themeTint" type="ST_UcharHexNumber" use="optional"/> + <xsd:attribute name="themeShade" type="ST_UcharHexNumber" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Rel"> + <xsd:attribute ref="r:id" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Object"> + <xsd:sequence> + <xsd:sequence maxOccurs="unbounded"> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:vml" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:office:office" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:element name="drawing" type="CT_Drawing" minOccurs="0"/> + <xsd:choice minOccurs="0"> + <xsd:element name="control" type="CT_Control"/> + <xsd:element name="objectLink" type="CT_ObjectLink"/> + <xsd:element name="objectEmbed" type="CT_ObjectEmbed"/> + <xsd:element name="movie" type="CT_Rel"/> + </xsd:choice> + </xsd:sequence> + <xsd:attribute name="dxaOrig" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="dyaOrig" type="s:ST_TwipsMeasure" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Picture"> + <xsd:sequence> + <xsd:sequence maxOccurs="unbounded"> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:vml" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:office:office" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:element name="movie" type="CT_Rel" minOccurs="0"/> + <xsd:element name="control" type="CT_Control" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ObjectEmbed"> + <xsd:attribute name="drawAspect" type="ST_ObjectDrawAspect" use="optional"/> + <xsd:attribute ref="r:id" use="required"/> + <xsd:attribute name="progId" type="s:ST_String" use="optional"/> + <xsd:attribute name="shapeId" type="s:ST_String" use="optional"/> + <xsd:attribute name="fieldCodes" type="s:ST_String" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_ObjectDrawAspect"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="content"/> + <xsd:enumeration value="icon"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ObjectLink"> + <xsd:complexContent> + <xsd:extension base="CT_ObjectEmbed"> + <xsd:attribute name="updateMode" type="ST_ObjectUpdateMode" use="required"/> + <xsd:attribute name="lockedField" type="s:ST_OnOff" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="ST_ObjectUpdateMode"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="always"/> + <xsd:enumeration value="onCall"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Drawing"> + <xsd:choice minOccurs="1" maxOccurs="unbounded"> + <xsd:element ref="wp:anchor" minOccurs="0"/> + <xsd:element ref="wp:inline" minOccurs="0"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_SimpleField"> + <xsd:sequence> + <xsd:element name="fldData" type="CT_Text" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="instr" type="s:ST_String" use="required"/> + <xsd:attribute name="fldLock" type="s:ST_OnOff"/> + <xsd:attribute name="dirty" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:simpleType name="ST_FldCharType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="begin"/> + <xsd:enumeration value="separate"/> + <xsd:enumeration value="end"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_InfoTextType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="text"/> + <xsd:enumeration value="autoText"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FFHelpTextVal"> + <xsd:restriction base="xsd:string"> + <xsd:maxLength value="256"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FFStatusTextVal"> + <xsd:restriction base="xsd:string"> + <xsd:maxLength value="140"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FFName"> + <xsd:restriction base="xsd:string"> + <xsd:maxLength value="65"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FFTextType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="regular"/> + <xsd:enumeration value="number"/> + <xsd:enumeration value="date"/> + <xsd:enumeration value="currentTime"/> + <xsd:enumeration value="currentDate"/> + <xsd:enumeration value="calculated"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FFTextType"> + <xsd:attribute name="val" type="ST_FFTextType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FFName"> + <xsd:attribute name="val" type="ST_FFName"/> + </xsd:complexType> + <xsd:complexType name="CT_FldChar"> + <xsd:choice> + <xsd:element name="fldData" type="CT_Text" minOccurs="0" maxOccurs="1"/> + <xsd:element name="ffData" type="CT_FFData" minOccurs="0" maxOccurs="1"/> + <xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0"/> + </xsd:choice> + <xsd:attribute name="fldCharType" type="ST_FldCharType" use="required"/> + <xsd:attribute name="fldLock" type="s:ST_OnOff"/> + <xsd:attribute name="dirty" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:complexType name="CT_Hyperlink"> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + <xsd:attribute name="tgtFrame" type="s:ST_String" use="optional"/> + <xsd:attribute name="tooltip" type="s:ST_String" use="optional"/> + <xsd:attribute name="docLocation" type="s:ST_String" use="optional"/> + <xsd:attribute name="history" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="anchor" type="s:ST_String" use="optional"/> + <xsd:attribute ref="r:id"/> + </xsd:complexType> + <xsd:complexType name="CT_FFData"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="name" type="CT_FFName"/> + <xsd:element name="label" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="tabIndex" type="CT_UnsignedDecimalNumber" minOccurs="0"/> + <xsd:element name="enabled" type="CT_OnOff"/> + <xsd:element name="calcOnExit" type="CT_OnOff"/> + <xsd:element name="entryMacro" type="CT_MacroName" minOccurs="0" maxOccurs="1"/> + <xsd:element name="exitMacro" type="CT_MacroName" minOccurs="0" maxOccurs="1"/> + <xsd:element name="helpText" type="CT_FFHelpText" minOccurs="0" maxOccurs="1"/> + <xsd:element name="statusText" type="CT_FFStatusText" minOccurs="0" maxOccurs="1"/> + <xsd:choice> + <xsd:element name="checkBox" type="CT_FFCheckBox"/> + <xsd:element name="ddList" type="CT_FFDDList"/> + <xsd:element name="textInput" type="CT_FFTextInput"/> + </xsd:choice> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_FFHelpText"> + <xsd:attribute name="type" type="ST_InfoTextType"/> + <xsd:attribute name="val" type="ST_FFHelpTextVal"/> + </xsd:complexType> + <xsd:complexType name="CT_FFStatusText"> + <xsd:attribute name="type" type="ST_InfoTextType"/> + <xsd:attribute name="val" type="ST_FFStatusTextVal"/> + </xsd:complexType> + <xsd:complexType name="CT_FFCheckBox"> + <xsd:sequence> + <xsd:choice> + <xsd:element name="size" type="CT_HpsMeasure"/> + <xsd:element name="sizeAuto" type="CT_OnOff"/> + </xsd:choice> + <xsd:element name="default" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="checked" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FFDDList"> + <xsd:sequence> + <xsd:element name="result" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="default" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="listEntry" type="CT_String" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FFTextInput"> + <xsd:sequence> + <xsd:element name="type" type="CT_FFTextType" minOccurs="0"/> + <xsd:element name="default" type="CT_String" minOccurs="0"/> + <xsd:element name="maxLength" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="format" type="CT_String" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_SectionMark"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="nextPage"/> + <xsd:enumeration value="nextColumn"/> + <xsd:enumeration value="continuous"/> + <xsd:enumeration value="evenPage"/> + <xsd:enumeration value="oddPage"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SectType"> + <xsd:attribute name="val" type="ST_SectionMark"/> + </xsd:complexType> + <xsd:complexType name="CT_PaperSource"> + <xsd:attribute name="first" type="ST_DecimalNumber"/> + <xsd:attribute name="other" type="ST_DecimalNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_NumberFormat"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="decimal"/> + <xsd:enumeration value="upperRoman"/> + <xsd:enumeration value="lowerRoman"/> + <xsd:enumeration value="upperLetter"/> + <xsd:enumeration value="lowerLetter"/> + <xsd:enumeration value="ordinal"/> + <xsd:enumeration value="cardinalText"/> + <xsd:enumeration value="ordinalText"/> + <xsd:enumeration value="hex"/> + <xsd:enumeration value="chicago"/> + <xsd:enumeration value="ideographDigital"/> + <xsd:enumeration value="japaneseCounting"/> + <xsd:enumeration value="aiueo"/> + <xsd:enumeration value="iroha"/> + <xsd:enumeration value="decimalFullWidth"/> + <xsd:enumeration value="decimalHalfWidth"/> + <xsd:enumeration value="japaneseLegal"/> + <xsd:enumeration value="japaneseDigitalTenThousand"/> + <xsd:enumeration value="decimalEnclosedCircle"/> + <xsd:enumeration value="decimalFullWidth2"/> + <xsd:enumeration value="aiueoFullWidth"/> + <xsd:enumeration value="irohaFullWidth"/> + <xsd:enumeration value="decimalZero"/> + <xsd:enumeration value="bullet"/> + <xsd:enumeration value="ganada"/> + <xsd:enumeration value="chosung"/> + <xsd:enumeration value="decimalEnclosedFullstop"/> + <xsd:enumeration value="decimalEnclosedParen"/> + <xsd:enumeration value="decimalEnclosedCircleChinese"/> + <xsd:enumeration value="ideographEnclosedCircle"/> + <xsd:enumeration value="ideographTraditional"/> + <xsd:enumeration value="ideographZodiac"/> + <xsd:enumeration value="ideographZodiacTraditional"/> + <xsd:enumeration value="taiwaneseCounting"/> + <xsd:enumeration value="ideographLegalTraditional"/> + <xsd:enumeration value="taiwaneseCountingThousand"/> + <xsd:enumeration value="taiwaneseDigital"/> + <xsd:enumeration value="chineseCounting"/> + <xsd:enumeration value="chineseLegalSimplified"/> + <xsd:enumeration value="chineseCountingThousand"/> + <xsd:enumeration value="koreanDigital"/> + <xsd:enumeration value="koreanCounting"/> + <xsd:enumeration value="koreanLegal"/> + <xsd:enumeration value="koreanDigital2"/> + <xsd:enumeration value="vietnameseCounting"/> + <xsd:enumeration value="russianLower"/> + <xsd:enumeration value="russianUpper"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="numberInDash"/> + <xsd:enumeration value="hebrew1"/> + <xsd:enumeration value="hebrew2"/> + <xsd:enumeration value="arabicAlpha"/> + <xsd:enumeration value="arabicAbjad"/> + <xsd:enumeration value="hindiVowels"/> + <xsd:enumeration value="hindiConsonants"/> + <xsd:enumeration value="hindiNumbers"/> + <xsd:enumeration value="hindiCounting"/> + <xsd:enumeration value="thaiLetters"/> + <xsd:enumeration value="thaiNumbers"/> + <xsd:enumeration value="thaiCounting"/> + <xsd:enumeration value="bahtText"/> + <xsd:enumeration value="dollarText"/> + <xsd:enumeration value="custom"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PageOrientation"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="portrait"/> + <xsd:enumeration value="landscape"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PageSz"> + <xsd:attribute name="w" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="h" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="orient" type="ST_PageOrientation" use="optional"/> + <xsd:attribute name="code" type="ST_DecimalNumber" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PageMar"> + <xsd:attribute name="top" type="ST_SignedTwipsMeasure" use="required"/> + <xsd:attribute name="right" type="s:ST_TwipsMeasure" use="required"/> + <xsd:attribute name="bottom" type="ST_SignedTwipsMeasure" use="required"/> + <xsd:attribute name="left" type="s:ST_TwipsMeasure" use="required"/> + <xsd:attribute name="header" type="s:ST_TwipsMeasure" use="required"/> + <xsd:attribute name="footer" type="s:ST_TwipsMeasure" use="required"/> + <xsd:attribute name="gutter" type="s:ST_TwipsMeasure" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_PageBorderZOrder"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="front"/> + <xsd:enumeration value="back"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PageBorderDisplay"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="allPages"/> + <xsd:enumeration value="firstPage"/> + <xsd:enumeration value="notFirstPage"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PageBorderOffset"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="page"/> + <xsd:enumeration value="text"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PageBorders"> + <xsd:sequence> + <xsd:element name="top" type="CT_TopPageBorder" minOccurs="0"/> + <xsd:element name="left" type="CT_PageBorder" minOccurs="0"/> + <xsd:element name="bottom" type="CT_BottomPageBorder" minOccurs="0"/> + <xsd:element name="right" type="CT_PageBorder" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="zOrder" type="ST_PageBorderZOrder" use="optional" default="front"/> + <xsd:attribute name="display" type="ST_PageBorderDisplay" use="optional"/> + <xsd:attribute name="offsetFrom" type="ST_PageBorderOffset" use="optional" default="text"/> + </xsd:complexType> + <xsd:complexType name="CT_PageBorder"> + <xsd:complexContent> + <xsd:extension base="CT_Border"> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_BottomPageBorder"> + <xsd:complexContent> + <xsd:extension base="CT_PageBorder"> + <xsd:attribute ref="r:bottomLeft" use="optional"/> + <xsd:attribute ref="r:bottomRight" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TopPageBorder"> + <xsd:complexContent> + <xsd:extension base="CT_PageBorder"> + <xsd:attribute ref="r:topLeft" use="optional"/> + <xsd:attribute ref="r:topRight" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:simpleType name="ST_ChapterSep"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="hyphen"/> + <xsd:enumeration value="period"/> + <xsd:enumeration value="colon"/> + <xsd:enumeration value="emDash"/> + <xsd:enumeration value="enDash"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_LineNumberRestart"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="newPage"/> + <xsd:enumeration value="newSection"/> + <xsd:enumeration value="continuous"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LineNumber"> + <xsd:attribute name="countBy" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="start" type="ST_DecimalNumber" use="optional" default="1"/> + <xsd:attribute name="distance" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="restart" type="ST_LineNumberRestart" use="optional" default="newPage"/> + </xsd:complexType> + <xsd:complexType name="CT_PageNumber"> + <xsd:attribute name="fmt" type="ST_NumberFormat" use="optional" default="decimal"/> + <xsd:attribute name="start" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="chapStyle" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="chapSep" type="ST_ChapterSep" use="optional" default="hyphen"/> + </xsd:complexType> + <xsd:complexType name="CT_Column"> + <xsd:attribute name="w" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="space" type="s:ST_TwipsMeasure" use="optional" default="0"/> + </xsd:complexType> + <xsd:complexType name="CT_Columns"> + <xsd:sequence minOccurs="0"> + <xsd:element name="col" type="CT_Column" maxOccurs="45"/> + </xsd:sequence> + <xsd:attribute name="equalWidth" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="space" type="s:ST_TwipsMeasure" use="optional" default="720"/> + <xsd:attribute name="num" type="ST_DecimalNumber" use="optional" default="1"/> + <xsd:attribute name="sep" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_VerticalJc"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="top"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="both"/> + <xsd:enumeration value="bottom"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_VerticalJc"> + <xsd:attribute name="val" type="ST_VerticalJc" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_DocGrid"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="default"/> + <xsd:enumeration value="lines"/> + <xsd:enumeration value="linesAndChars"/> + <xsd:enumeration value="snapToChars"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DocGrid"> + <xsd:attribute name="type" type="ST_DocGrid"/> + <xsd:attribute name="linePitch" type="ST_DecimalNumber"/> + <xsd:attribute name="charSpace" type="ST_DecimalNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_HdrFtr"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="even"/> + <xsd:enumeration value="default"/> + <xsd:enumeration value="first"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_FtnEdn"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="separator"/> + <xsd:enumeration value="continuationSeparator"/> + <xsd:enumeration value="continuationNotice"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_HdrFtrRef"> + <xsd:complexContent> + <xsd:extension base="CT_Rel"> + <xsd:attribute name="type" type="ST_HdrFtr" use="required"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:group name="EG_HdrFtrReferences"> + <xsd:choice> + <xsd:element name="headerReference" type="CT_HdrFtrRef" minOccurs="0"/> + <xsd:element name="footerReference" type="CT_HdrFtrRef" minOccurs="0"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_HdrFtr"> + <xsd:group ref="EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:group name="EG_SectPrContents"> + <xsd:sequence> + <xsd:element name="footnotePr" type="CT_FtnProps" minOccurs="0"/> + <xsd:element name="endnotePr" type="CT_EdnProps" minOccurs="0"/> + <xsd:element name="type" type="CT_SectType" minOccurs="0"/> + <xsd:element name="pgSz" type="CT_PageSz" minOccurs="0"/> + <xsd:element name="pgMar" type="CT_PageMar" minOccurs="0"/> + <xsd:element name="paperSrc" type="CT_PaperSource" minOccurs="0"/> + <xsd:element name="pgBorders" type="CT_PageBorders" minOccurs="0"/> + <xsd:element name="lnNumType" type="CT_LineNumber" minOccurs="0"/> + <xsd:element name="pgNumType" type="CT_PageNumber" minOccurs="0"/> + <xsd:element name="cols" type="CT_Columns" minOccurs="0"/> + <xsd:element name="formProt" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="vAlign" type="CT_VerticalJc" minOccurs="0"/> + <xsd:element name="noEndnote" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="titlePg" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0"/> + <xsd:element name="bidi" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="rtlGutter" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="docGrid" type="CT_DocGrid" minOccurs="0"/> + <xsd:element name="printerSettings" type="CT_Rel" minOccurs="0"/> + </xsd:sequence> + </xsd:group> + <xsd:attributeGroup name="AG_SectPrAttributes"> + <xsd:attribute name="rsidRPr" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidDel" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidR" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidSect" type="ST_LongHexNumber"/> + </xsd:attributeGroup> + <xsd:complexType name="CT_SectPrBase"> + <xsd:sequence> + <xsd:group ref="EG_SectPrContents" minOccurs="0"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_SectPrAttributes"/> + </xsd:complexType> + <xsd:complexType name="CT_SectPr"> + <xsd:sequence> + <xsd:group ref="EG_HdrFtrReferences" minOccurs="0" maxOccurs="6"/> + <xsd:group ref="EG_SectPrContents" minOccurs="0"/> + <xsd:element name="sectPrChange" type="CT_SectPrChange" minOccurs="0"/> + </xsd:sequence> + <xsd:attributeGroup ref="AG_SectPrAttributes"/> + </xsd:complexType> + <xsd:simpleType name="ST_BrType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="page"/> + <xsd:enumeration value="column"/> + <xsd:enumeration value="textWrapping"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_BrClear"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + <xsd:enumeration value="all"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Br"> + <xsd:attribute name="type" type="ST_BrType" use="optional"/> + <xsd:attribute name="clear" type="ST_BrClear" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_PTabAlignment"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="left"/> + <xsd:enumeration value="center"/> + <xsd:enumeration value="right"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PTabRelativeTo"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="margin"/> + <xsd:enumeration value="indent"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_PTabLeader"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="dot"/> + <xsd:enumeration value="hyphen"/> + <xsd:enumeration value="underscore"/> + <xsd:enumeration value="middleDot"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_PTab"> + <xsd:attribute name="alignment" type="ST_PTabAlignment" use="required"/> + <xsd:attribute name="relativeTo" type="ST_PTabRelativeTo" use="required"/> + <xsd:attribute name="leader" type="ST_PTabLeader" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Sym"> + <xsd:attribute name="font" type="s:ST_String"/> + <xsd:attribute name="char" type="ST_ShortHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_ProofErr"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="spellStart"/> + <xsd:enumeration value="spellEnd"/> + <xsd:enumeration value="gramStart"/> + <xsd:enumeration value="gramEnd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ProofErr"> + <xsd:attribute name="type" type="ST_ProofErr" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_EdGrp"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="everyone"/> + <xsd:enumeration value="administrators"/> + <xsd:enumeration value="contributors"/> + <xsd:enumeration value="editors"/> + <xsd:enumeration value="owners"/> + <xsd:enumeration value="current"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Perm"> + <xsd:attribute name="id" type="s:ST_String" use="required"/> + <xsd:attribute name="displacedByCustomXml" type="ST_DisplacedByCustomXml" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_PermStart"> + <xsd:complexContent> + <xsd:extension base="CT_Perm"> + <xsd:attribute name="edGrp" type="ST_EdGrp" use="optional"/> + <xsd:attribute name="ed" type="s:ST_String" use="optional"/> + <xsd:attribute name="colFirst" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="colLast" type="ST_DecimalNumber" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </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:group name="EG_RunInnerContent"> + <xsd:choice> + <xsd:element name="br" type="CT_Br"/> + <xsd:element name="t" type="CT_Text"/> + <xsd:element name="contentPart" type="CT_Rel"/> + <xsd:element name="delText" type="CT_Text"/> + <xsd:element name="instrText" type="CT_Text"/> + <xsd:element name="delInstrText" type="CT_Text"/> + <xsd:element name="noBreakHyphen" type="CT_Empty"/> + <xsd:element name="softHyphen" type="CT_Empty" minOccurs="0"/> + <xsd:element name="dayShort" type="CT_Empty" minOccurs="0"/> + <xsd:element name="monthShort" type="CT_Empty" minOccurs="0"/> + <xsd:element name="yearShort" type="CT_Empty" minOccurs="0"/> + <xsd:element name="dayLong" type="CT_Empty" minOccurs="0"/> + <xsd:element name="monthLong" type="CT_Empty" minOccurs="0"/> + <xsd:element name="yearLong" type="CT_Empty" minOccurs="0"/> + <xsd:element name="annotationRef" type="CT_Empty" minOccurs="0"/> + <xsd:element name="footnoteRef" type="CT_Empty" minOccurs="0"/> + <xsd:element name="endnoteRef" type="CT_Empty" minOccurs="0"/> + <xsd:element name="separator" type="CT_Empty" minOccurs="0"/> + <xsd:element name="continuationSeparator" type="CT_Empty" minOccurs="0"/> + <xsd:element name="sym" type="CT_Sym" minOccurs="0"/> + <xsd:element name="pgNum" type="CT_Empty" minOccurs="0"/> + <xsd:element name="cr" type="CT_Empty" minOccurs="0"/> + <xsd:element name="tab" type="CT_Empty" minOccurs="0"/> + <xsd:element name="object" type="CT_Object"/> + <xsd:element name="pict" type="CT_Picture"/> + <xsd:element name="fldChar" type="CT_FldChar"/> + <xsd:element name="ruby" type="CT_Ruby"/> + <xsd:element name="footnoteReference" type="CT_FtnEdnRef"/> + <xsd:element name="endnoteReference" type="CT_FtnEdnRef"/> + <xsd:element name="commentReference" type="CT_Markup"/> + <xsd:element name="drawing" type="CT_Drawing"/> + <xsd:element name="ptab" type="CT_PTab" minOccurs="0"/> + <xsd:element name="lastRenderedPageBreak" type="CT_Empty" minOccurs="0" maxOccurs="1"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_R"> + <xsd:sequence> + <xsd:group ref="EG_RPr" minOccurs="0"/> + <xsd:group ref="EG_RunInnerContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="rsidRPr" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidDel" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidR" type="ST_LongHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_Hint"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="default"/> + <xsd:enumeration value="eastAsia"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_Theme"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="majorEastAsia"/> + <xsd:enumeration value="majorBidi"/> + <xsd:enumeration value="majorAscii"/> + <xsd:enumeration value="majorHAnsi"/> + <xsd:enumeration value="minorEastAsia"/> + <xsd:enumeration value="minorBidi"/> + <xsd:enumeration value="minorAscii"/> + <xsd:enumeration value="minorHAnsi"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Fonts"> + <xsd:attribute name="hint" type="ST_Hint"/> + <xsd:attribute name="ascii" type="s:ST_String"/> + <xsd:attribute name="hAnsi" type="s:ST_String"/> + <xsd:attribute name="eastAsia" type="s:ST_String"/> + <xsd:attribute name="cs" type="s:ST_String"/> + <xsd:attribute name="asciiTheme" type="ST_Theme"/> + <xsd:attribute name="hAnsiTheme" type="ST_Theme"/> + <xsd:attribute name="eastAsiaTheme" type="ST_Theme"/> + <xsd:attribute name="cstheme" type="ST_Theme"/> + </xsd:complexType> + <xsd:group name="EG_RPrBase"> + <xsd:choice> + <xsd:element name="rStyle" type="CT_String"/> + <xsd:element name="rFonts" type="CT_Fonts"/> + <xsd:element name="b" type="CT_OnOff"/> + <xsd:element name="bCs" type="CT_OnOff"/> + <xsd:element name="i" type="CT_OnOff"/> + <xsd:element name="iCs" type="CT_OnOff"/> + <xsd:element name="caps" type="CT_OnOff"/> + <xsd:element name="smallCaps" type="CT_OnOff"/> + <xsd:element name="strike" type="CT_OnOff"/> + <xsd:element name="dstrike" type="CT_OnOff"/> + <xsd:element name="outline" type="CT_OnOff"/> + <xsd:element name="shadow" type="CT_OnOff"/> + <xsd:element name="emboss" type="CT_OnOff"/> + <xsd:element name="imprint" type="CT_OnOff"/> + <xsd:element name="noProof" type="CT_OnOff"/> + <xsd:element name="snapToGrid" type="CT_OnOff"/> + <xsd:element name="vanish" type="CT_OnOff"/> + <xsd:element name="webHidden" type="CT_OnOff"/> + <xsd:element name="color" type="CT_Color"/> + <xsd:element name="spacing" type="CT_SignedTwipsMeasure"/> + <xsd:element name="w" type="CT_TextScale"/> + <xsd:element name="kern" type="CT_HpsMeasure"/> + <xsd:element name="position" type="CT_SignedHpsMeasure"/> + <xsd:element name="sz" type="CT_HpsMeasure"/> + <xsd:element name="szCs" type="CT_HpsMeasure"/> + <xsd:element name="highlight" type="CT_Highlight"/> + <xsd:element name="u" type="CT_Underline"/> + <xsd:element name="effect" type="CT_TextEffect"/> + <xsd:element name="bdr" type="CT_Border"/> + <xsd:element name="shd" type="CT_Shd"/> + <xsd:element name="fitText" type="CT_FitText"/> + <xsd:element name="vertAlign" type="CT_VerticalAlignRun"/> + <xsd:element name="rtl" type="CT_OnOff"/> + <xsd:element name="cs" type="CT_OnOff"/> + <xsd:element name="em" type="CT_Em"/> + <xsd:element name="lang" type="CT_Language"/> + <xsd:element name="eastAsianLayout" type="CT_EastAsianLayout"/> + <xsd:element name="specVanish" type="CT_OnOff"/> + <xsd:element name="oMath" type="CT_OnOff"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_RPrContent"> + <xsd:sequence> + <xsd:group ref="EG_RPrBase" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rPrChange" type="CT_RPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_RPr"> + <xsd:sequence> + <xsd:group ref="EG_RPrContent" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_RPr"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + </xsd:sequence> + </xsd:group> + <xsd:group name="EG_RPrMath"> + <xsd:choice> + <xsd:group ref="EG_RPr"/> + <xsd:element name="ins" type="CT_MathCtrlIns"/> + <xsd:element name="del" type="CT_MathCtrlDel"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_MathCtrlIns"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:choice minOccurs="0"> + <xsd:element name="del" type="CT_RPrChange" minOccurs="1"/> + <xsd:element name="rPr" type="CT_RPr" minOccurs="1"/> + </xsd:choice> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_MathCtrlDel"> + <xsd:complexContent> + <xsd:extension base="CT_TrackChange"> + <xsd:choice minOccurs="0"> + <xsd:element name="rPr" type="CT_RPr" minOccurs="1"/> + </xsd:choice> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_RPrOriginal"> + <xsd:sequence> + <xsd:group ref="EG_RPrBase" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ParaRPrOriginal"> + <xsd:sequence> + <xsd:group ref="EG_ParaRPrTrackChanges" minOccurs="0"/> + <xsd:group ref="EG_RPrBase" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ParaRPr"> + <xsd:sequence> + <xsd:group ref="EG_ParaRPrTrackChanges" minOccurs="0"/> + <xsd:group ref="EG_RPrBase" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="rPrChange" type="CT_ParaRPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_ParaRPrTrackChanges"> + <xsd:sequence> + <xsd:element name="ins" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="del" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="moveFrom" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="moveTo" type="CT_TrackChange" minOccurs="0"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_AltChunk"> + <xsd:sequence> + <xsd:element name="altChunkPr" type="CT_AltChunkPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute ref="r:id" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_AltChunkPr"> + <xsd:sequence> + <xsd:element name="matchSrc" type="CT_OnOff" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_RubyAlign"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="center"/> + <xsd:enumeration value="distributeLetter"/> + <xsd:enumeration value="distributeSpace"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + <xsd:enumeration value="rightVertical"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_RubyAlign"> + <xsd:attribute name="val" type="ST_RubyAlign" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_RubyPr"> + <xsd:sequence> + <xsd:element name="rubyAlign" type="CT_RubyAlign"/> + <xsd:element name="hps" type="CT_HpsMeasure"/> + <xsd:element name="hpsRaise" type="CT_HpsMeasure"/> + <xsd:element name="hpsBaseText" type="CT_HpsMeasure"/> + <xsd:element name="lid" type="CT_Lang"/> + <xsd:element name="dirty" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_RubyContent"> + <xsd:choice> + <xsd:element name="r" type="CT_R"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_RubyContent"> + <xsd:group ref="EG_RubyContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:complexType name="CT_Ruby"> + <xsd:sequence> + <xsd:element name="rubyPr" type="CT_RubyPr"/> + <xsd:element name="rt" type="CT_RubyContent"/> + <xsd:element name="rubyBase" type="CT_RubyContent"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Lock"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="sdtLocked"/> + <xsd:enumeration value="contentLocked"/> + <xsd:enumeration value="unlocked"/> + <xsd:enumeration value="sdtContentLocked"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Lock"> + <xsd:attribute name="val" type="ST_Lock"/> + </xsd:complexType> + <xsd:complexType name="CT_SdtListItem"> + <xsd:attribute name="displayText" type="s:ST_String"/> + <xsd:attribute name="value" type="s:ST_String"/> + </xsd:complexType> + <xsd:simpleType name="ST_SdtDateMappingType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="text"/> + <xsd:enumeration value="date"/> + <xsd:enumeration value="dateTime"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SdtDateMappingType"> + <xsd:attribute name="val" type="ST_SdtDateMappingType"/> + </xsd:complexType> + <xsd:complexType name="CT_CalendarType"> + <xsd:attribute name="val" type="s:ST_CalendarType"/> + </xsd:complexType> + <xsd:complexType name="CT_SdtDate"> + <xsd:sequence> + <xsd:element name="dateFormat" type="CT_String" minOccurs="0"/> + <xsd:element name="lid" type="CT_Lang" minOccurs="0"/> + <xsd:element name="storeMappedDataAs" type="CT_SdtDateMappingType" minOccurs="0"/> + <xsd:element name="calendar" type="CT_CalendarType" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="fullDate" type="ST_DateTime" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_SdtComboBox"> + <xsd:sequence> + <xsd:element name="listItem" type="CT_SdtListItem" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="lastValue" type="s:ST_String" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_SdtDocPart"> + <xsd:sequence> + <xsd:element name="docPartGallery" type="CT_String" minOccurs="0"/> + <xsd:element name="docPartCategory" type="CT_String" minOccurs="0"/> + <xsd:element name="docPartUnique" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtDropDownList"> + <xsd:sequence> + <xsd:element name="listItem" type="CT_SdtListItem" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="lastValue" type="s:ST_String" use="optional" default=""/> + </xsd:complexType> + <xsd:complexType name="CT_Placeholder"> + <xsd:sequence> + <xsd:element name="docPart" type="CT_String"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtText"> + <xsd:attribute name="multiLine" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:complexType name="CT_DataBinding"> + <xsd:attribute name="prefixMappings" type="s:ST_String"/> + <xsd:attribute name="xpath" type="s:ST_String" use="required"/> + <xsd:attribute name="storeItemID" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SdtPr"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + <xsd:element name="alias" type="CT_String" minOccurs="0"/> + <xsd:element name="tag" type="CT_String" minOccurs="0"/> + <xsd:element name="id" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="lock" type="CT_Lock" minOccurs="0"/> + <xsd:element name="placeholder" type="CT_Placeholder" minOccurs="0"/> + <xsd:element name="temporary" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="showingPlcHdr" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="dataBinding" type="CT_DataBinding" minOccurs="0"/> + <xsd:element name="label" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="tabIndex" type="CT_UnsignedDecimalNumber" minOccurs="0"/> + <xsd:choice minOccurs="0" maxOccurs="1"> + <xsd:element name="equation" type="CT_Empty"/> + <xsd:element name="comboBox" type="CT_SdtComboBox"/> + <xsd:element name="date" type="CT_SdtDate"/> + <xsd:element name="docPartObj" type="CT_SdtDocPart"/> + <xsd:element name="docPartList" type="CT_SdtDocPart"/> + <xsd:element name="dropDownList" type="CT_SdtDropDownList"/> + <xsd:element name="picture" type="CT_Empty"/> + <xsd:element name="richText" type="CT_Empty"/> + <xsd:element name="text" type="CT_SdtText"/> + <xsd:element name="citation" type="CT_Empty"/> + <xsd:element name="group" type="CT_Empty"/> + <xsd:element name="bibliography" type="CT_Empty"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtEndPr"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + </xsd:choice> + </xsd:complexType> + <xsd:group name="EG_ContentRunContent"> + <xsd:choice> + <xsd:element name="customXml" type="CT_CustomXmlRun"/> + <xsd:element name="smartTag" type="CT_SmartTagRun"/> + <xsd:element name="sdt" type="CT_SdtRun"/> + <xsd:element name="dir" type="CT_DirContentRun"/> + <xsd:element name="bdo" type="CT_BdoContentRun"/> + <xsd:element name="r" type="CT_R"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_DirContentRun"> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + <xsd:attribute name="val" type="ST_Direction" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_BdoContentRun"> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + <xsd:attribute name="val" type="ST_Direction" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Direction"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="ltr"/> + <xsd:enumeration value="rtl"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_SdtContentRun"> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:group name="EG_ContentBlockContent"> + <xsd:choice> + <xsd:element name="customXml" type="CT_CustomXmlBlock"/> + <xsd:element name="sdt" type="CT_SdtBlock"/> + <xsd:element name="p" type="CT_P" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="unbounded"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_SdtContentBlock"> + <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:group name="EG_ContentRowContent"> + <xsd:choice> + <xsd:element name="tr" type="CT_Row" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="customXml" type="CT_CustomXmlRow"/> + <xsd:element name="sdt" type="CT_SdtRow"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_SdtContentRow"> + <xsd:group ref="EG_ContentRowContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:group name="EG_ContentCellContent"> + <xsd:choice> + <xsd:element name="tc" type="CT_Tc" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="customXml" type="CT_CustomXmlCell"/> + <xsd:element name="sdt" type="CT_SdtCell"/> + <xsd:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_SdtContentCell"> + <xsd:group ref="EG_ContentCellContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:complexType name="CT_SdtBlock"> + <xsd:sequence> + <xsd:element name="sdtPr" type="CT_SdtPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtEndPr" type="CT_SdtEndPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtContent" type="CT_SdtContentBlock" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtRun"> + <xsd:sequence> + <xsd:element name="sdtPr" type="CT_SdtPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtEndPr" type="CT_SdtEndPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtContent" type="CT_SdtContentRun" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtCell"> + <xsd:sequence> + <xsd:element name="sdtPr" type="CT_SdtPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtEndPr" type="CT_SdtEndPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtContent" type="CT_SdtContentCell" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_SdtRow"> + <xsd:sequence> + <xsd:element name="sdtPr" type="CT_SdtPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtEndPr" type="CT_SdtEndPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sdtContent" type="CT_SdtContentRow" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Attr"> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + <xsd:attribute name="val" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomXmlRun"> + <xsd:sequence> + <xsd:element name="customXmlPr" type="CT_CustomXmlPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="element" type="s:ST_XmlName" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SmartTagRun"> + <xsd:sequence> + <xsd:element name="smartTagPr" type="CT_SmartTagPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="element" type="s:ST_XmlName" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomXmlBlock"> + <xsd:sequence> + <xsd:element name="customXmlPr" type="CT_CustomXmlPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="element" type="s:ST_XmlName" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomXmlPr"> + <xsd:sequence> + <xsd:element name="placeholder" type="CT_String" minOccurs="0"/> + <xsd:element name="attr" type="CT_Attr" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CustomXmlRow"> + <xsd:sequence> + <xsd:element name="customXmlPr" type="CT_CustomXmlPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ContentRowContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="element" type="s:ST_XmlName" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_CustomXmlCell"> + <xsd:sequence> + <xsd:element name="customXmlPr" type="CT_CustomXmlPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ContentCellContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="element" type="s:ST_XmlName" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SmartTagPr"> + <xsd:sequence> + <xsd:element name="attr" type="CT_Attr" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:group name="EG_PContent"> + <xsd:choice> + <xsd:group ref="EG_ContentRunContent" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="fldSimple" type="CT_SimpleField" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="hyperlink" type="CT_Hyperlink"/> + <xsd:element name="subDoc" type="CT_Rel"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_P"> + <xsd:sequence> + <xsd:element name="pPr" type="CT_PPr" minOccurs="0"/> + <xsd:group ref="EG_PContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="rsidRPr" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidR" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidDel" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidP" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidRDefault" type="ST_LongHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_TblWidth"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="nil"/> + <xsd:enumeration value="pct"/> + <xsd:enumeration value="dxa"/> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Height"> + <xsd:attribute name="val" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="hRule" type="ST_HeightRule"/> + </xsd:complexType> + <xsd:simpleType name="ST_MeasurementOrPercent"> + <xsd:union memberTypes="ST_DecimalNumberOrPercent s:ST_UniversalMeasure"/> + </xsd:simpleType> + <xsd:complexType name="CT_TblWidth"> + <xsd:attribute name="w" type="ST_MeasurementOrPercent"/> + <xsd:attribute name="type" type="ST_TblWidth"/> + </xsd:complexType> + <xsd:complexType name="CT_TblGridCol"> + <xsd:attribute name="w" type="s:ST_TwipsMeasure"/> + </xsd:complexType> + <xsd:complexType name="CT_TblGridBase"> + <xsd:sequence> + <xsd:element name="gridCol" type="CT_TblGridCol" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblGrid"> + <xsd:complexContent> + <xsd:extension base="CT_TblGridBase"> + <xsd:sequence> + <xsd:element name="tblGridChange" type="CT_TblGridChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TcBorders"> + <xsd:sequence> + <xsd:element name="top" type="CT_Border" minOccurs="0"/> + <xsd:element name="start" type="CT_Border" minOccurs="0"/> + <xsd:element name="left" type="CT_Border" minOccurs="0"/> + <xsd:element name="bottom" type="CT_Border" minOccurs="0"/> + <xsd:element name="end" type="CT_Border" minOccurs="0"/> + <xsd:element name="right" type="CT_Border" minOccurs="0"/> + <xsd:element name="insideH" type="CT_Border" minOccurs="0"/> + <xsd:element name="insideV" type="CT_Border" minOccurs="0"/> + <xsd:element name="tl2br" type="CT_Border" minOccurs="0"/> + <xsd:element name="tr2bl" type="CT_Border" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TcMar"> + <xsd:sequence> + <xsd:element name="top" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="start" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="left" type="CT_TblWidth" minOccurs="0"/> + <xsd:element name="bottom" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="end" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="right" type="CT_TblWidth" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_Merge"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="continue"/> + <xsd:enumeration value="restart"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_VMerge"> + <xsd:attribute name="val" type="ST_Merge"/> + </xsd:complexType> + <xsd:complexType name="CT_HMerge"> + <xsd:attribute name="val" type="ST_Merge"/> + </xsd:complexType> + <xsd:complexType name="CT_TcPrBase"> + <xsd:sequence> + <xsd:element name="cnfStyle" type="CT_Cnf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcW" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="gridSpan" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="hMerge" type="CT_HMerge" minOccurs="0"/> + <xsd:element name="vMerge" type="CT_VMerge" minOccurs="0"/> + <xsd:element name="tcBorders" type="CT_TcBorders" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shd" type="CT_Shd" minOccurs="0"/> + <xsd:element name="noWrap" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="tcMar" type="CT_TcMar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcFitText" type="CT_OnOff" minOccurs="0" maxOccurs="1"/> + <xsd:element name="vAlign" type="CT_VerticalJc" minOccurs="0"/> + <xsd:element name="hideMark" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="headers" type="CT_Headers" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TcPr"> + <xsd:complexContent> + <xsd:extension base="CT_TcPrInner"> + <xsd:sequence> + <xsd:element name="tcPrChange" type="CT_TcPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TcPrInner"> + <xsd:complexContent> + <xsd:extension base="CT_TcPrBase"> + <xsd:sequence> + <xsd:group ref="EG_CellMarkupElements" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Tc"> + <xsd:sequence> + <xsd:element name="tcPr" type="CT_TcPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="id" type="s:ST_String" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_Cnf"> + <xsd:restriction base="xsd:string"> + <xsd:length value="12"/> + <xsd:pattern value="[01]*"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Cnf"> + <xsd:attribute name="val" type="ST_Cnf"/> + <xsd:attribute name="firstRow" type="s:ST_OnOff"/> + <xsd:attribute name="lastRow" type="s:ST_OnOff"/> + <xsd:attribute name="firstColumn" type="s:ST_OnOff"/> + <xsd:attribute name="lastColumn" type="s:ST_OnOff"/> + <xsd:attribute name="oddVBand" type="s:ST_OnOff"/> + <xsd:attribute name="evenVBand" type="s:ST_OnOff"/> + <xsd:attribute name="oddHBand" type="s:ST_OnOff"/> + <xsd:attribute name="evenHBand" type="s:ST_OnOff"/> + <xsd:attribute name="firstRowFirstColumn" type="s:ST_OnOff"/> + <xsd:attribute name="firstRowLastColumn" type="s:ST_OnOff"/> + <xsd:attribute name="lastRowFirstColumn" type="s:ST_OnOff"/> + <xsd:attribute name="lastRowLastColumn" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:complexType name="CT_Headers"> + <xsd:sequence minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="header" type="CT_String"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TrPrBase"> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="cnfStyle" type="CT_Cnf" minOccurs="0" maxOccurs="1"/> + <xsd:element name="divId" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="gridBefore" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="gridAfter" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="wBefore" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="wAfter" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="cantSplit" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="trHeight" type="CT_Height" minOccurs="0"/> + <xsd:element name="tblHeader" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="tblCellSpacing" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="jc" type="CT_JcTable" minOccurs="0" maxOccurs="1"/> + <xsd:element name="hidden" type="CT_OnOff" minOccurs="0"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_TrPr"> + <xsd:complexContent> + <xsd:extension base="CT_TrPrBase"> + <xsd:sequence> + <xsd:element name="ins" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="del" type="CT_TrackChange" minOccurs="0"/> + <xsd:element name="trPrChange" type="CT_TrPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Row"> + <xsd:sequence> + <xsd:element name="tblPrEx" type="CT_TblPrEx" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trPr" type="CT_TrPr" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="EG_ContentCellContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="rsidRPr" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidR" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidDel" type="ST_LongHexNumber"/> + <xsd:attribute name="rsidTr" type="ST_LongHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_TblLayoutType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="fixed"/> + <xsd:enumeration value="autofit"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TblLayoutType"> + <xsd:attribute name="type" type="ST_TblLayoutType"/> + </xsd:complexType> + <xsd:simpleType name="ST_TblOverlap"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="never"/> + <xsd:enumeration value="overlap"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TblOverlap"> + <xsd:attribute name="val" type="ST_TblOverlap" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_TblPPr"> + <xsd:attribute name="leftFromText" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="rightFromText" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="topFromText" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="bottomFromText" type="s:ST_TwipsMeasure"/> + <xsd:attribute name="vertAnchor" type="ST_VAnchor"/> + <xsd:attribute name="horzAnchor" type="ST_HAnchor"/> + <xsd:attribute name="tblpXSpec" type="s:ST_XAlign"/> + <xsd:attribute name="tblpX" type="ST_SignedTwipsMeasure"/> + <xsd:attribute name="tblpYSpec" type="s:ST_YAlign"/> + <xsd:attribute name="tblpY" type="ST_SignedTwipsMeasure"/> + </xsd:complexType> + <xsd:complexType name="CT_TblCellMar"> + <xsd:sequence> + <xsd:element name="top" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="start" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="left" type="CT_TblWidth" minOccurs="0"/> + <xsd:element name="bottom" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="end" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="right" type="CT_TblWidth" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblBorders"> + <xsd:sequence> + <xsd:element name="top" type="CT_Border" minOccurs="0"/> + <xsd:element name="start" type="CT_Border" minOccurs="0"/> + <xsd:element name="left" type="CT_Border" minOccurs="0"/> + <xsd:element name="bottom" type="CT_Border" minOccurs="0"/> + <xsd:element name="end" type="CT_Border" minOccurs="0"/> + <xsd:element name="right" type="CT_Border" minOccurs="0"/> + <xsd:element name="insideH" type="CT_Border" minOccurs="0"/> + <xsd:element name="insideV" type="CT_Border" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblPrBase"> + <xsd:sequence> + <xsd:element name="tblStyle" type="CT_String" minOccurs="0"/> + <xsd:element name="tblpPr" type="CT_TblPPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblOverlap" type="CT_TblOverlap" minOccurs="0" maxOccurs="1"/> + <xsd:element name="bidiVisual" type="CT_OnOff" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblStyleRowBandSize" type="CT_DecimalNumber" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblStyleColBandSize" type="CT_DecimalNumber" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblW" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="jc" type="CT_JcTable" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblCellSpacing" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblInd" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblBorders" type="CT_TblBorders" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shd" type="CT_Shd" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblLayout" type="CT_TblLayoutType" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblCellMar" type="CT_TblCellMar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblLook" type="CT_TblLook" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblCaption" type="CT_String" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblDescription" type="CT_String" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblPr"> + <xsd:complexContent> + <xsd:extension base="CT_TblPrBase"> + <xsd:sequence> + <xsd:element name="tblPrChange" type="CT_TblPrChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_TblPrExBase"> + <xsd:sequence> + <xsd:element name="tblW" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="jc" type="CT_JcTable" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblCellSpacing" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblInd" type="CT_TblWidth" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblBorders" type="CT_TblBorders" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shd" type="CT_Shd" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblLayout" type="CT_TblLayoutType" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblCellMar" type="CT_TblCellMar" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblLook" type="CT_TblLook" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblPrEx"> + <xsd:complexContent> + <xsd:extension base="CT_TblPrExBase"> + <xsd:sequence> + <xsd:element name="tblPrExChange" type="CT_TblPrExChange" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Tbl"> + <xsd:sequence> + <xsd:group ref="EG_RangeMarkupElements" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="tblPr" type="CT_TblPr"/> + <xsd:element name="tblGrid" type="CT_TblGrid"/> + <xsd:group ref="EG_ContentRowContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TblLook"> + <xsd:attribute name="firstRow" type="s:ST_OnOff"/> + <xsd:attribute name="lastRow" type="s:ST_OnOff"/> + <xsd:attribute name="firstColumn" type="s:ST_OnOff"/> + <xsd:attribute name="lastColumn" type="s:ST_OnOff"/> + <xsd:attribute name="noHBand" type="s:ST_OnOff"/> + <xsd:attribute name="noVBand" type="s:ST_OnOff"/> + <xsd:attribute name="val" type="ST_ShortHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_FtnPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="pageBottom"/> + <xsd:enumeration value="beneathText"/> + <xsd:enumeration value="sectEnd"/> + <xsd:enumeration value="docEnd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FtnPos"> + <xsd:attribute name="val" type="ST_FtnPos" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_EdnPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="sectEnd"/> + <xsd:enumeration value="docEnd"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_EdnPos"> + <xsd:attribute name="val" type="ST_EdnPos" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_NumFmt"> + <xsd:attribute name="val" type="ST_NumberFormat" use="required"/> + <xsd:attribute name="format" type="s:ST_String" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_RestartNumber"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="continuous"/> + <xsd:enumeration value="eachSect"/> + <xsd:enumeration value="eachPage"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_NumRestart"> + <xsd:attribute name="val" type="ST_RestartNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FtnEdnRef"> + <xsd:attribute name="customMarkFollows" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="id" use="required" type="ST_DecimalNumber"/> + </xsd:complexType> + <xsd:complexType name="CT_FtnEdnSepRef"> + <xsd:attribute name="id" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FtnEdn"> + <xsd:sequence> + <xsd:group ref="EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_FtnEdn" use="optional"/> + <xsd:attribute name="id" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:group name="EG_FtnEdnNumProps"> + <xsd:sequence> + <xsd:element name="numStart" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="numRestart" type="CT_NumRestart" minOccurs="0"/> + </xsd:sequence> + </xsd:group> + <xsd:complexType name="CT_FtnProps"> + <xsd:sequence> + <xsd:element name="pos" type="CT_FtnPos" minOccurs="0"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/> + <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_EdnProps"> + <xsd:sequence> + <xsd:element name="pos" type="CT_EdnPos" minOccurs="0"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/> + <xsd:group ref="EG_FtnEdnNumProps" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_FtnDocProps"> + <xsd:complexContent> + <xsd:extension base="CT_FtnProps"> + <xsd:sequence> + <xsd:element name="footnote" type="CT_FtnEdnSepRef" minOccurs="0" maxOccurs="3"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_EdnDocProps"> + <xsd:complexContent> + <xsd:extension base="CT_EdnProps"> + <xsd:sequence> + <xsd:element name="endnote" type="CT_FtnEdnSepRef" minOccurs="0" maxOccurs="3"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_RecipientData"> + <xsd:sequence> + <xsd:element name="active" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="column" type="CT_DecimalNumber" minOccurs="1"/> + <xsd:element name="uniqueTag" type="CT_Base64Binary" minOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Base64Binary"> + <xsd:attribute name="val" type="xsd:base64Binary" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Recipients"> + <xsd:sequence> + <xsd:element name="recipientData" type="CT_RecipientData" minOccurs="1" maxOccurs="unbounded" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="recipients" type="CT_Recipients"/> + <xsd:complexType name="CT_OdsoFieldMapData"> + <xsd:sequence> + <xsd:element name="type" type="CT_MailMergeOdsoFMDFieldType" minOccurs="0"/> + <xsd:element name="name" type="CT_String" minOccurs="0"/> + <xsd:element name="mappedName" type="CT_String" minOccurs="0"/> + <xsd:element name="column" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="lid" type="CT_Lang" minOccurs="0"/> + <xsd:element name="dynamicAddress" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_MailMergeSourceType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="database"/> + <xsd:enumeration value="addressBook"/> + <xsd:enumeration value="document1"/> + <xsd:enumeration value="document2"/> + <xsd:enumeration value="text"/> + <xsd:enumeration value="email"/> + <xsd:enumeration value="native"/> + <xsd:enumeration value="legacy"/> + <xsd:enumeration value="master"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MailMergeSourceType"> + <xsd:attribute name="val" use="required" type="ST_MailMergeSourceType"/> + </xsd:complexType> + <xsd:complexType name="CT_Odso"> + <xsd:sequence> + <xsd:element name="udl" type="CT_String" minOccurs="0"/> + <xsd:element name="table" type="CT_String" minOccurs="0"/> + <xsd:element name="src" type="CT_Rel" minOccurs="0"/> + <xsd:element name="colDelim" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="type" type="CT_MailMergeSourceType" minOccurs="0"/> + <xsd:element name="fHdr" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="fieldMapData" type="CT_OdsoFieldMapData" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="recipientData" type="CT_Rel" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_MailMerge"> + <xsd:sequence> + <xsd:element name="mainDocumentType" type="CT_MailMergeDocType" minOccurs="1"/> + <xsd:element name="linkToQuery" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="dataType" type="CT_MailMergeDataType" minOccurs="1"/> + <xsd:element name="connectString" type="CT_String" minOccurs="0"/> + <xsd:element name="query" type="CT_String" minOccurs="0"/> + <xsd:element name="dataSource" type="CT_Rel" minOccurs="0"/> + <xsd:element name="headerSource" type="CT_Rel" minOccurs="0"/> + <xsd:element name="doNotSuppressBlankLines" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="destination" type="CT_MailMergeDest" minOccurs="0"/> + <xsd:element name="addressFieldName" type="CT_String" minOccurs="0"/> + <xsd:element name="mailSubject" type="CT_String" minOccurs="0"/> + <xsd:element name="mailAsAttachment" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="viewMergedData" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="activeRecord" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="checkErrors" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="odso" type="CT_Odso" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TargetScreenSz"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="544x376"/> + <xsd:enumeration value="640x480"/> + <xsd:enumeration value="720x512"/> + <xsd:enumeration value="800x600"/> + <xsd:enumeration value="1024x768"/> + <xsd:enumeration value="1152x882"/> + <xsd:enumeration value="1152x900"/> + <xsd:enumeration value="1280x1024"/> + <xsd:enumeration value="1600x1200"/> + <xsd:enumeration value="1800x1440"/> + <xsd:enumeration value="1920x1200"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TargetScreenSz"> + <xsd:attribute name="val" type="ST_TargetScreenSz" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Compat"> + <xsd:sequence> + <xsd:element name="useSingleBorderforContiguousCells" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="wpJustification" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noTabHangInd" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noLeading" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="spaceForUL" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noColumnBalance" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="balanceSingleByteDoubleByteWidth" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noExtraLineSpacing" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotLeaveBackslashAlone" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="ulTrailSpace" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotExpandShiftReturn" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="spacingInWholePoints" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="lineWrapLikeWord6" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="printBodyTextBeforeHeader" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="printColBlack" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="wpSpaceWidth" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="showBreaksInFrames" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="subFontBySize" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressBottomSpacing" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressTopSpacing" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressSpacingAtTopOfPage" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressTopSpacingWP" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suppressSpBfAfterPgBrk" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="swapBordersFacingPages" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="convMailMergeEsc" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="truncateFontHeightsLikeWP6" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="mwSmallCaps" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="usePrinterMetrics" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotSuppressParagraphBorders" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="wrapTrailSpaces" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="footnoteLayoutLikeWW8" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="shapeLayoutLikeWW8" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="alignTablesRowByRow" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="forgetLastTabAlignment" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="adjustLineHeightInTable" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="autoSpaceLikeWord95" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noSpaceRaiseLower" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotUseHTMLParagraphAutoSpacing" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="layoutRawTableWidth" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="layoutTableRowsApart" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useWord97LineBreakRules" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotBreakWrappedTables" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotSnapToGridInCell" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="selectFldWithFirstOrLastChar" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="applyBreakingRules" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotWrapTextWithPunct" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotUseEastAsianBreakRules" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useWord2002TableStyleRules" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="growAutofit" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useFELayout" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useNormalStyleForList" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotUseIndentAsNumberingTabStop" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useAltKinsokuLineBreakRules" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="allowSpaceOfSameStyleInTable" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotSuppressIndentation" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotAutofitConstrainedTables" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="autofitToFirstFixedWidthCell" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="underlineTabInNumList" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="displayHangulFixedWidth" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="splitPgBreakAndParaMark" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotVertAlignCellWithSp" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotBreakConstrainedForcedTable" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotVertAlignInTxbx" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useAnsiKerningPairs" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="cachedColBalance" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="compatSetting" type="CT_CompatSetting" minOccurs="0" maxOccurs="unbounded" + /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_CompatSetting"> + <xsd:attribute name="name" type="s:ST_String"/> + <xsd:attribute name="uri" type="s:ST_String"/> + <xsd:attribute name="val" type="s:ST_String"/> + </xsd:complexType> + <xsd:complexType name="CT_DocVar"> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + <xsd:attribute name="val" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DocVars"> + <xsd:sequence> + <xsd:element name="docVar" type="CT_DocVar" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DocRsids"> + <xsd:sequence> + <xsd:element name="rsidRoot" type="CT_LongHexNumber" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rsid" type="CT_LongHexNumber" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_CharacterSpacing"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="doNotCompress"/> + <xsd:enumeration value="compressPunctuation"/> + <xsd:enumeration value="compressPunctuationAndJapaneseKana"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_CharacterSpacing"> + <xsd:attribute name="val" type="ST_CharacterSpacing" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_SaveThroughXslt"> + <xsd:attribute ref="r:id" use="optional"/> + <xsd:attribute name="solutionID" type="s:ST_String" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_RPrDefault"> + <xsd:sequence> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_PPrDefault"> + <xsd:sequence> + <xsd:element name="pPr" type="CT_PPrGeneral" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DocDefaults"> + <xsd:sequence> + <xsd:element name="rPrDefault" type="CT_RPrDefault" minOccurs="0"/> + <xsd:element name="pPrDefault" type="CT_PPrDefault" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_WmlColorSchemeIndex"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="dark1"/> + <xsd:enumeration value="light1"/> + <xsd:enumeration value="dark2"/> + <xsd:enumeration value="light2"/> + <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="hyperlink"/> + <xsd:enumeration value="followedHyperlink"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_ColorSchemeMapping"> + <xsd:attribute name="bg1" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="t1" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="bg2" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="t2" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent1" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent2" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent3" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent4" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent5" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="accent6" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="hyperlink" type="ST_WmlColorSchemeIndex"/> + <xsd:attribute name="followedHyperlink" type="ST_WmlColorSchemeIndex"/> + </xsd:complexType> + <xsd:complexType name="CT_ReadingModeInkLockDown"> + <xsd:attribute name="actualPg" type="s:ST_OnOff" use="required"/> + <xsd:attribute name="w" type="ST_PixelsMeasure" use="required"/> + <xsd:attribute name="h" type="ST_PixelsMeasure" use="required"/> + <xsd:attribute name="fontSz" type="ST_DecimalNumberOrPercent" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_WriteProtection"> + <xsd:attribute name="recommended" type="s:ST_OnOff" use="optional"/> + <xsd:attributeGroup ref="AG_Password"/> + <xsd:attributeGroup ref="AG_TransitionalPassword"/> + </xsd:complexType> + <xsd:complexType name="CT_Settings"> + <xsd:sequence> + <xsd:element name="writeProtection" type="CT_WriteProtection" minOccurs="0"/> + <xsd:element name="view" type="CT_View" minOccurs="0"/> + <xsd:element name="zoom" type="CT_Zoom" minOccurs="0"/> + <xsd:element name="removePersonalInformation" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="removeDateAndTime" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotDisplayPageBoundaries" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="displayBackgroundShape" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="printPostScriptOverText" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="printFractionalCharacterWidth" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="printFormsData" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="embedTrueTypeFonts" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="embedSystemFonts" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="saveSubsetFonts" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="saveFormsData" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="mirrorMargins" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="alignBordersAndEdges" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bordersDoNotSurroundHeader" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bordersDoNotSurroundFooter" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="gutterAtTop" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="hideSpellingErrors" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="hideGrammaticalErrors" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="activeWritingStyle" type="CT_WritingStyle" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element name="proofState" type="CT_Proof" minOccurs="0"/> + <xsd:element name="formsDesign" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="attachedTemplate" type="CT_Rel" minOccurs="0"/> + <xsd:element name="linkStyles" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="stylePaneFormatFilter" type="CT_StylePaneFilter" minOccurs="0"/> + <xsd:element name="stylePaneSortMethod" type="CT_StyleSort" minOccurs="0"/> + <xsd:element name="documentType" type="CT_DocType" minOccurs="0"/> + <xsd:element name="mailMerge" type="CT_MailMerge" minOccurs="0"/> + <xsd:element name="revisionView" type="CT_TrackChangesView" minOccurs="0"/> + <xsd:element name="trackRevisions" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotTrackMoves" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotTrackFormatting" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="documentProtection" type="CT_DocProtect" minOccurs="0"/> + <xsd:element name="autoFormatOverride" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="styleLockTheme" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="styleLockQFSet" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="defaultTabStop" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="autoHyphenation" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="consecutiveHyphenLimit" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="hyphenationZone" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="doNotHyphenateCaps" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="showEnvelope" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="summaryLength" type="CT_DecimalNumberOrPrecent" minOccurs="0"/> + <xsd:element name="clickAndTypeStyle" type="CT_String" minOccurs="0"/> + <xsd:element name="defaultTableStyle" type="CT_String" minOccurs="0"/> + <xsd:element name="evenAndOddHeaders" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bookFoldRevPrinting" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bookFoldPrinting" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bookFoldPrintingSheets" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="drawingGridHorizontalSpacing" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="drawingGridVerticalSpacing" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="displayHorizontalDrawingGridEvery" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="displayVerticalDrawingGridEvery" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="doNotUseMarginsForDrawingGridOrigin" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="drawingGridHorizontalOrigin" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="drawingGridVerticalOrigin" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="doNotShadeFormData" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noPunctuationKerning" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="characterSpacingControl" type="CT_CharacterSpacing" minOccurs="0"/> + <xsd:element name="printTwoOnOne" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="strictFirstAndLastChars" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="noLineBreaksAfter" type="CT_Kinsoku" minOccurs="0"/> + <xsd:element name="noLineBreaksBefore" type="CT_Kinsoku" minOccurs="0"/> + <xsd:element name="savePreviewPicture" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotValidateAgainstSchema" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="saveInvalidXml" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="ignoreMixedContent" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="alwaysShowPlaceholderText" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotDemarcateInvalidXml" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="saveXmlDataOnly" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="useXSLTWhenSaving" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="saveThroughXslt" type="CT_SaveThroughXslt" minOccurs="0"/> + <xsd:element name="showXMLTags" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="alwaysMergeEmptyNamespace" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="updateFields" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="hdrShapeDefaults" type="CT_ShapeDefaults" minOccurs="0"/> + <xsd:element name="footnotePr" type="CT_FtnDocProps" minOccurs="0"/> + <xsd:element name="endnotePr" type="CT_EdnDocProps" minOccurs="0"/> + <xsd:element name="compat" type="CT_Compat" minOccurs="0"/> + <xsd:element name="docVars" type="CT_DocVars" minOccurs="0"/> + <xsd:element name="rsids" type="CT_DocRsids" minOccurs="0"/> + <xsd:element ref="m:mathPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="attachedSchema" type="CT_String" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="themeFontLang" type="CT_Language" minOccurs="0" maxOccurs="1"/> + <xsd:element name="clrSchemeMapping" type="CT_ColorSchemeMapping" minOccurs="0"/> + <xsd:element name="doNotIncludeSubdocsInStats" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotAutoCompressPictures" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="forceUpgrade" type="CT_Empty" minOccurs="0" maxOccurs="1"/> + <xsd:element name="captions" type="CT_Captions" minOccurs="0" maxOccurs="1"/> + <xsd:element name="readModeInkLockDown" type="CT_ReadingModeInkLockDown" minOccurs="0"/> + <xsd:element name="smartTagType" type="CT_SmartTagType" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="sl:schemaLibrary" minOccurs="0" maxOccurs="1"/> + <xsd:element name="shapeDefaults" type="CT_ShapeDefaults" minOccurs="0"/> + <xsd:element name="doNotEmbedSmartTags" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="decimalSymbol" type="CT_String" minOccurs="0" maxOccurs="1"/> + <xsd:element name="listSeparator" type="CT_String" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_StyleSort"> + <xsd:attribute name="val" type="ST_StyleSort" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_StylePaneFilter"> + <xsd:attribute name="allStyles" type="s:ST_OnOff"/> + <xsd:attribute name="customStyles" type="s:ST_OnOff"/> + <xsd:attribute name="latentStyles" type="s:ST_OnOff"/> + <xsd:attribute name="stylesInUse" type="s:ST_OnOff"/> + <xsd:attribute name="headingStyles" type="s:ST_OnOff"/> + <xsd:attribute name="numberingStyles" type="s:ST_OnOff"/> + <xsd:attribute name="tableStyles" type="s:ST_OnOff"/> + <xsd:attribute name="directFormattingOnRuns" type="s:ST_OnOff"/> + <xsd:attribute name="directFormattingOnParagraphs" type="s:ST_OnOff"/> + <xsd:attribute name="directFormattingOnNumbering" type="s:ST_OnOff"/> + <xsd:attribute name="directFormattingOnTables" type="s:ST_OnOff"/> + <xsd:attribute name="clearFormatting" type="s:ST_OnOff"/> + <xsd:attribute name="top3HeadingStyles" type="s:ST_OnOff"/> + <xsd:attribute name="visibleStyles" type="s:ST_OnOff"/> + <xsd:attribute name="alternateStyleNames" type="s:ST_OnOff"/> + <xsd:attribute name="val" type="ST_ShortHexNumber"/> + </xsd:complexType> + <xsd:simpleType name="ST_StyleSort"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="name"/> + <xsd:enumeration value="priority"/> + <xsd:enumeration value="default"/> + <xsd:enumeration value="font"/> + <xsd:enumeration value="basedOn"/> + <xsd:enumeration value="type"/> + <xsd:enumeration value="0000"/> + <xsd:enumeration value="0001"/> + <xsd:enumeration value="0002"/> + <xsd:enumeration value="0003"/> + <xsd:enumeration value="0004"/> + <xsd:enumeration value="0005"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_WebSettings"> + <xsd:sequence> + <xsd:element name="frameset" type="CT_Frameset" minOccurs="0"/> + <xsd:element name="divs" type="CT_Divs" minOccurs="0"/> + <xsd:element name="encoding" type="CT_String" minOccurs="0"/> + <xsd:element name="optimizeForBrowser" type="CT_OptimizeForBrowser" minOccurs="0"/> + <xsd:element name="relyOnVML" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="allowPNG" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotRelyOnCSS" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotSaveAsSingleFile" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotOrganizeInFolder" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="doNotUseLongFileNames" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="pixelsPerInch" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="targetScreenSz" type="CT_TargetScreenSz" minOccurs="0"/> + <xsd:element name="saveSmartTagsAsXml" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_FrameScrollbar"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="on"/> + <xsd:enumeration value="off"/> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FrameScrollbar"> + <xsd:attribute name="val" type="ST_FrameScrollbar" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_OptimizeForBrowser"> + <xsd:complexContent> + <xsd:extension base="CT_OnOff"> + <xsd:attribute name="target" type="s:ST_String" use="optional"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Frame"> + <xsd:sequence> + <xsd:element name="sz" type="CT_String" minOccurs="0"/> + <xsd:element name="name" type="CT_String" minOccurs="0"/> + <xsd:element name="title" type="CT_String" minOccurs="0"/> + <xsd:element name="longDesc" type="CT_Rel" minOccurs="0"/> + <xsd:element name="sourceFileName" type="CT_Rel" minOccurs="0"/> + <xsd:element name="marW" type="CT_PixelsMeasure" minOccurs="0"/> + <xsd:element name="marH" type="CT_PixelsMeasure" minOccurs="0"/> + <xsd:element name="scrollbar" type="CT_FrameScrollbar" minOccurs="0"/> + <xsd:element name="noResizeAllowed" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="linkedToFile" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_FrameLayout"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="rows"/> + <xsd:enumeration value="cols"/> + <xsd:enumeration value="none"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FrameLayout"> + <xsd:attribute name="val" type="ST_FrameLayout" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FramesetSplitbar"> + <xsd:sequence> + <xsd:element name="w" type="CT_TwipsMeasure" minOccurs="0"/> + <xsd:element name="color" type="CT_Color" minOccurs="0"/> + <xsd:element name="noBorder" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="flatBorders" type="CT_OnOff" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Frameset"> + <xsd:sequence> + <xsd:element name="sz" type="CT_String" minOccurs="0"/> + <xsd:element name="framesetSplitbar" type="CT_FramesetSplitbar" minOccurs="0"/> + <xsd:element name="frameLayout" type="CT_FrameLayout" minOccurs="0"/> + <xsd:element name="title" type="CT_String" minOccurs="0"/> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element name="frameset" type="CT_Frameset" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="frame" type="CT_Frame" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_NumPicBullet"> + <xsd:choice> + <xsd:element name="pict" type="CT_Picture"/> + <xsd:element name="drawing" type="CT_Drawing"/> + </xsd:choice> + <xsd:attribute name="numPicBulletId" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_LevelSuffix"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="tab"/> + <xsd:enumeration value="space"/> + <xsd:enumeration value="nothing"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_LevelSuffix"> + <xsd:attribute name="val" type="ST_LevelSuffix" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_LevelText"> + <xsd:attribute name="val" type="s:ST_String" use="optional"/> + <xsd:attribute name="null" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_LvlLegacy"> + <xsd:attribute name="legacy" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="legacySpace" type="s:ST_TwipsMeasure" use="optional"/> + <xsd:attribute name="legacyIndent" type="ST_SignedTwipsMeasure" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_Lvl"> + <xsd:sequence> + <xsd:element name="start" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/> + <xsd:element name="lvlRestart" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="pStyle" type="CT_String" minOccurs="0"/> + <xsd:element name="isLgl" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="suff" type="CT_LevelSuffix" minOccurs="0"/> + <xsd:element name="lvlText" type="CT_LevelText" minOccurs="0"/> + <xsd:element name="lvlPicBulletId" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="legacy" type="CT_LvlLegacy" minOccurs="0"/> + <xsd:element name="lvlJc" type="CT_Jc" minOccurs="0"/> + <xsd:element name="pPr" type="CT_PPrGeneral" minOccurs="0"/> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + </xsd:sequence> + <xsd:attribute name="ilvl" type="ST_DecimalNumber" use="required"/> + <xsd:attribute name="tplc" type="ST_LongHexNumber" use="optional"/> + <xsd:attribute name="tentative" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_MultiLevelType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="singleLevel"/> + <xsd:enumeration value="multilevel"/> + <xsd:enumeration value="hybridMultilevel"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_MultiLevelType"> + <xsd:attribute name="val" type="ST_MultiLevelType" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AbstractNum"> + <xsd:sequence> + <xsd:element name="nsid" type="CT_LongHexNumber" minOccurs="0"/> + <xsd:element name="multiLevelType" type="CT_MultiLevelType" minOccurs="0"/> + <xsd:element name="tmpl" type="CT_LongHexNumber" minOccurs="0"/> + <xsd:element name="name" type="CT_String" minOccurs="0"/> + <xsd:element name="styleLink" type="CT_String" minOccurs="0"/> + <xsd:element name="numStyleLink" type="CT_String" minOccurs="0"/> + <xsd:element name="lvl" type="CT_Lvl" minOccurs="0" maxOccurs="9"/> + </xsd:sequence> + <xsd:attribute name="abstractNumId" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_NumLvl"> + <xsd:sequence> + <xsd:element name="startOverride" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="lvl" type="CT_Lvl" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="ilvl" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Num"> + <xsd:sequence> + <xsd:element name="abstractNumId" type="CT_DecimalNumber" minOccurs="1"/> + <xsd:element name="lvlOverride" type="CT_NumLvl" minOccurs="0" maxOccurs="9"/> + </xsd:sequence> + <xsd:attribute name="numId" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Numbering"> + <xsd:sequence> + <xsd:element name="numPicBullet" type="CT_NumPicBullet" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="abstractNum" type="CT_AbstractNum" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="num" type="CT_Num" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="numIdMacAtCleanup" type="CT_DecimalNumber" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:simpleType name="ST_TblStyleOverrideType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="wholeTable"/> + <xsd:enumeration value="firstRow"/> + <xsd:enumeration value="lastRow"/> + <xsd:enumeration value="firstCol"/> + <xsd:enumeration value="lastCol"/> + <xsd:enumeration value="band1Vert"/> + <xsd:enumeration value="band2Vert"/> + <xsd:enumeration value="band1Horz"/> + <xsd:enumeration value="band2Horz"/> + <xsd:enumeration value="neCell"/> + <xsd:enumeration value="nwCell"/> + <xsd:enumeration value="seCell"/> + <xsd:enumeration value="swCell"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_TblStylePr"> + <xsd:sequence> + <xsd:element name="pPr" type="CT_PPrGeneral" minOccurs="0"/> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0"/> + <xsd:element name="tblPr" type="CT_TblPrBase" minOccurs="0"/> + <xsd:element name="trPr" type="CT_TrPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcPr" type="CT_TcPr" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_TblStyleOverrideType" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_StyleType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="paragraph"/> + <xsd:enumeration value="character"/> + <xsd:enumeration value="table"/> + <xsd:enumeration value="numbering"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Style"> + <xsd:sequence> + <xsd:element name="name" type="CT_String" minOccurs="0" maxOccurs="1"/> + <xsd:element name="aliases" type="CT_String" minOccurs="0"/> + <xsd:element name="basedOn" type="CT_String" minOccurs="0"/> + <xsd:element name="next" type="CT_String" minOccurs="0"/> + <xsd:element name="link" type="CT_String" minOccurs="0"/> + <xsd:element name="autoRedefine" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="hidden" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="uiPriority" type="CT_DecimalNumber" minOccurs="0"/> + <xsd:element name="semiHidden" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="unhideWhenUsed" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="qFormat" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="locked" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="personal" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="personalCompose" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="personalReply" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="rsid" type="CT_LongHexNumber" minOccurs="0"/> + <xsd:element name="pPr" type="CT_PPrGeneral" minOccurs="0" maxOccurs="1"/> + <xsd:element name="rPr" type="CT_RPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblPr" type="CT_TblPrBase" minOccurs="0" maxOccurs="1"/> + <xsd:element name="trPr" type="CT_TrPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tcPr" type="CT_TcPr" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tblStylePr" type="CT_TblStylePr" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="type" type="ST_StyleType" use="optional"/> + <xsd:attribute name="styleId" type="s:ST_String" use="optional"/> + <xsd:attribute name="default" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="customStyle" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_LsdException"> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + <xsd:attribute name="locked" type="s:ST_OnOff"/> + <xsd:attribute name="uiPriority" type="ST_DecimalNumber"/> + <xsd:attribute name="semiHidden" type="s:ST_OnOff"/> + <xsd:attribute name="unhideWhenUsed" type="s:ST_OnOff"/> + <xsd:attribute name="qFormat" type="s:ST_OnOff"/> + </xsd:complexType> + <xsd:complexType name="CT_LatentStyles"> + <xsd:sequence> + <xsd:element name="lsdException" type="CT_LsdException" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="defLockedState" type="s:ST_OnOff"/> + <xsd:attribute name="defUIPriority" type="ST_DecimalNumber"/> + <xsd:attribute name="defSemiHidden" type="s:ST_OnOff"/> + <xsd:attribute name="defUnhideWhenUsed" type="s:ST_OnOff"/> + <xsd:attribute name="defQFormat" type="s:ST_OnOff"/> + <xsd:attribute name="count" type="ST_DecimalNumber"/> + </xsd:complexType> + <xsd:complexType name="CT_Styles"> + <xsd:sequence> + <xsd:element name="docDefaults" type="CT_DocDefaults" minOccurs="0"/> + <xsd:element name="latentStyles" type="CT_LatentStyles" minOccurs="0" maxOccurs="1"/> + <xsd:element name="style" type="CT_Style" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Panose"> + <xsd:attribute name="val" type="s:ST_Panose" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_FontFamily"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="decorative"/> + <xsd:enumeration value="modern"/> + <xsd:enumeration value="roman"/> + <xsd:enumeration value="script"/> + <xsd:enumeration value="swiss"/> + <xsd:enumeration value="auto"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_FontFamily"> + <xsd:attribute name="val" type="ST_FontFamily" use="required"/> + </xsd:complexType> + <xsd:simpleType name="ST_Pitch"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="fixed"/> + <xsd:enumeration value="variable"/> + <xsd:enumeration value="default"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Pitch"> + <xsd:attribute name="val" type="ST_Pitch" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FontSig"> + <xsd:attribute name="usb0" use="required" type="ST_LongHexNumber"/> + <xsd:attribute name="usb1" use="required" type="ST_LongHexNumber"/> + <xsd:attribute name="usb2" use="required" type="ST_LongHexNumber"/> + <xsd:attribute name="usb3" use="required" type="ST_LongHexNumber"/> + <xsd:attribute name="csb0" use="required" type="ST_LongHexNumber"/> + <xsd:attribute name="csb1" use="required" type="ST_LongHexNumber"/> + </xsd:complexType> + <xsd:complexType name="CT_FontRel"> + <xsd:complexContent> + <xsd:extension base="CT_Rel"> + <xsd:attribute name="fontKey" type="s:ST_Guid"/> + <xsd:attribute name="subsetted" type="s:ST_OnOff"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_Font"> + <xsd:sequence> + <xsd:element name="altName" type="CT_String" minOccurs="0" maxOccurs="1"/> + <xsd:element name="panose1" type="CT_Panose" minOccurs="0" maxOccurs="1"/> + <xsd:element name="charset" type="CT_Charset" minOccurs="0" maxOccurs="1"/> + <xsd:element name="family" type="CT_FontFamily" minOccurs="0" maxOccurs="1"/> + <xsd:element name="notTrueType" type="CT_OnOff" minOccurs="0" maxOccurs="1"/> + <xsd:element name="pitch" type="CT_Pitch" minOccurs="0" maxOccurs="1"/> + <xsd:element name="sig" type="CT_FontSig" minOccurs="0" maxOccurs="1"/> + <xsd:element name="embedRegular" type="CT_FontRel" minOccurs="0" maxOccurs="1"/> + <xsd:element name="embedBold" type="CT_FontRel" minOccurs="0" maxOccurs="1"/> + <xsd:element name="embedItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/> + <xsd:element name="embedBoldItalic" type="CT_FontRel" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_FontsList"> + <xsd:sequence> + <xsd:element name="font" type="CT_Font" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DivBdr"> + <xsd:sequence> + <xsd:element name="top" type="CT_Border" minOccurs="0"/> + <xsd:element name="left" type="CT_Border" minOccurs="0"/> + <xsd:element name="bottom" type="CT_Border" minOccurs="0"/> + <xsd:element name="right" type="CT_Border" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Div"> + <xsd:sequence> + <xsd:element name="blockQuote" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="bodyDiv" type="CT_OnOff" minOccurs="0"/> + <xsd:element name="marLeft" type="CT_SignedTwipsMeasure"/> + <xsd:element name="marRight" type="CT_SignedTwipsMeasure"/> + <xsd:element name="marTop" type="CT_SignedTwipsMeasure"/> + <xsd:element name="marBottom" type="CT_SignedTwipsMeasure"/> + <xsd:element name="divBdr" type="CT_DivBdr" minOccurs="0"/> + <xsd:element name="divsChild" type="CT_Divs" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="id" type="ST_DecimalNumber" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_Divs"> + <xsd:sequence minOccurs="1" maxOccurs="unbounded"> + <xsd:element name="div" type="CT_Div"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_TxbxContent"> + <xsd:group ref="EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/> + </xsd:complexType> + <xsd:element name="txbxContent" type="CT_TxbxContent"/> + <xsd:group name="EG_MathContent"> + <xsd:choice> + <xsd:element ref="m:oMathPara"/> + <xsd:element ref="m:oMath"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_BlockLevelChunkElts"> + <xsd:choice> + <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_BlockLevelElts"> + <xsd:choice> + <xsd:group ref="EG_BlockLevelChunkElts" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="altChunk" type="CT_AltChunk" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:group name="EG_RunLevelElts"> + <xsd:choice> + <xsd:element name="proofErr" minOccurs="0" type="CT_ProofErr"/> + <xsd:element name="permStart" minOccurs="0" type="CT_PermStart"/> + <xsd:element name="permEnd" minOccurs="0" type="CT_Perm"/> + <xsd:group ref="EG_RangeMarkupElements" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="ins" type="CT_RunTrackChange" minOccurs="0"/> + <xsd:element name="del" type="CT_RunTrackChange" minOccurs="0"/> + <xsd:element name="moveFrom" type="CT_RunTrackChange"/> + <xsd:element name="moveTo" type="CT_RunTrackChange"/> + <xsd:group ref="EG_MathContent" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:group> + <xsd:complexType name="CT_Body"> + <xsd:sequence> + <xsd:group ref="EG_BlockLevelElts" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element name="sectPr" minOccurs="0" maxOccurs="1" type="CT_SectPr"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_ShapeDefaults"> + <xsd:choice maxOccurs="unbounded"> + <xsd:any processContents="lax" namespace="urn:schemas-microsoft-com:office:office" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:complexType> + <xsd:complexType name="CT_Comments"> + <xsd:sequence> + <xsd:element name="comment" type="CT_Comment" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="comments" type="CT_Comments"/> + <xsd:complexType name="CT_Footnotes"> + <xsd:sequence maxOccurs="unbounded"> + <xsd:element name="footnote" type="CT_FtnEdn" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="footnotes" type="CT_Footnotes"/> + <xsd:complexType name="CT_Endnotes"> + <xsd:sequence maxOccurs="unbounded"> + <xsd:element name="endnote" type="CT_FtnEdn" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="endnotes" type="CT_Endnotes"/> + <xsd:element name="hdr" type="CT_HdrFtr"/> + <xsd:element name="ftr" type="CT_HdrFtr"/> + <xsd:complexType name="CT_SmartTagType"> + <xsd:attribute name="namespaceuri" type="s:ST_String"/> + <xsd:attribute name="name" type="s:ST_String"/> + <xsd:attribute name="url" type="s:ST_String"/> + </xsd:complexType> + <xsd:simpleType name="ST_ThemeColor"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="dark1"/> + <xsd:enumeration value="light1"/> + <xsd:enumeration value="dark2"/> + <xsd:enumeration value="light2"/> + <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="hyperlink"/> + <xsd:enumeration value="followedHyperlink"/> + <xsd:enumeration value="none"/> + <xsd:enumeration value="background1"/> + <xsd:enumeration value="text1"/> + <xsd:enumeration value="background2"/> + <xsd:enumeration value="text2"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="ST_DocPartBehavior"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="content"/> + <xsd:enumeration value="p"/> + <xsd:enumeration value="pg"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DocPartBehavior"> + <xsd:attribute name="val" use="required" type="ST_DocPartBehavior"/> + </xsd:complexType> + <xsd:complexType name="CT_DocPartBehaviors"> + <xsd:choice> + <xsd:element name="behavior" type="CT_DocPartBehavior" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:complexType> + <xsd:simpleType name="ST_DocPartType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="none"/> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="autoExp"/> + <xsd:enumeration value="toolbar"/> + <xsd:enumeration value="speller"/> + <xsd:enumeration value="formFld"/> + <xsd:enumeration value="bbPlcHdr"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DocPartType"> + <xsd:attribute name="val" use="required" type="ST_DocPartType"/> + </xsd:complexType> + <xsd:complexType name="CT_DocPartTypes"> + <xsd:choice> + <xsd:element name="type" type="CT_DocPartType" maxOccurs="unbounded"/> + </xsd:choice> + <xsd:attribute name="all" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:simpleType name="ST_DocPartGallery"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="placeholder"/> + <xsd:enumeration value="any"/> + <xsd:enumeration value="default"/> + <xsd:enumeration value="docParts"/> + <xsd:enumeration value="coverPg"/> + <xsd:enumeration value="eq"/> + <xsd:enumeration value="ftrs"/> + <xsd:enumeration value="hdrs"/> + <xsd:enumeration value="pgNum"/> + <xsd:enumeration value="tbls"/> + <xsd:enumeration value="watermarks"/> + <xsd:enumeration value="autoTxt"/> + <xsd:enumeration value="txtBox"/> + <xsd:enumeration value="pgNumT"/> + <xsd:enumeration value="pgNumB"/> + <xsd:enumeration value="pgNumMargins"/> + <xsd:enumeration value="tblOfContents"/> + <xsd:enumeration value="bib"/> + <xsd:enumeration value="custQuickParts"/> + <xsd:enumeration value="custCoverPg"/> + <xsd:enumeration value="custEq"/> + <xsd:enumeration value="custFtrs"/> + <xsd:enumeration value="custHdrs"/> + <xsd:enumeration value="custPgNum"/> + <xsd:enumeration value="custTbls"/> + <xsd:enumeration value="custWatermarks"/> + <xsd:enumeration value="custAutoTxt"/> + <xsd:enumeration value="custTxtBox"/> + <xsd:enumeration value="custPgNumT"/> + <xsd:enumeration value="custPgNumB"/> + <xsd:enumeration value="custPgNumMargins"/> + <xsd:enumeration value="custTblOfContents"/> + <xsd:enumeration value="custBib"/> + <xsd:enumeration value="custom1"/> + <xsd:enumeration value="custom2"/> + <xsd:enumeration value="custom3"/> + <xsd:enumeration value="custom4"/> + <xsd:enumeration value="custom5"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_DocPartGallery"> + <xsd:attribute name="val" type="ST_DocPartGallery" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_DocPartCategory"> + <xsd:sequence> + <xsd:element name="name" type="CT_String" minOccurs="1" maxOccurs="1"/> + <xsd:element name="gallery" type="CT_DocPartGallery" minOccurs="1" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DocPartName"> + <xsd:attribute name="val" type="s:ST_String" use="required"/> + <xsd:attribute name="decorated" type="s:ST_OnOff" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_DocPartPr"> + <xsd:all> + <xsd:element name="name" type="CT_DocPartName" minOccurs="1"/> + <xsd:element name="style" type="CT_String" minOccurs="0"/> + <xsd:element name="category" type="CT_DocPartCategory" minOccurs="0"/> + <xsd:element name="types" type="CT_DocPartTypes" minOccurs="0"/> + <xsd:element name="behaviors" type="CT_DocPartBehaviors" minOccurs="0"/> + <xsd:element name="description" type="CT_String" minOccurs="0"/> + <xsd:element name="guid" type="CT_Guid" minOccurs="0"/> + </xsd:all> + </xsd:complexType> + <xsd:complexType name="CT_DocPart"> + <xsd:sequence> + <xsd:element name="docPartPr" type="CT_DocPartPr" minOccurs="0"/> + <xsd:element name="docPartBody" type="CT_Body" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DocParts"> + <xsd:choice> + <xsd:element name="docPart" type="CT_DocPart" minOccurs="1" maxOccurs="unbounded"/> + </xsd:choice> + </xsd:complexType> + <xsd:element name="settings" type="CT_Settings"/> + <xsd:element name="webSettings" type="CT_WebSettings"/> + <xsd:element name="fonts" type="CT_FontsList"/> + <xsd:element name="numbering" type="CT_Numbering"/> + <xsd:element name="styles" type="CT_Styles"/> + <xsd:simpleType name="ST_CaptionPos"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="above"/> + <xsd:enumeration value="below"/> + <xsd:enumeration value="left"/> + <xsd:enumeration value="right"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:complexType name="CT_Caption"> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + <xsd:attribute name="pos" type="ST_CaptionPos" use="optional"/> + <xsd:attribute name="chapNum" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="heading" type="ST_DecimalNumber" use="optional"/> + <xsd:attribute name="noLabel" type="s:ST_OnOff" use="optional"/> + <xsd:attribute name="numFmt" type="ST_NumberFormat" use="optional"/> + <xsd:attribute name="sep" type="ST_ChapterSep" use="optional"/> + </xsd:complexType> + <xsd:complexType name="CT_AutoCaption"> + <xsd:attribute name="name" type="s:ST_String" use="required"/> + <xsd:attribute name="caption" type="s:ST_String" use="required"/> + </xsd:complexType> + <xsd:complexType name="CT_AutoCaptions"> + <xsd:sequence> + <xsd:element name="autoCaption" type="CT_AutoCaption" minOccurs="1" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Captions"> + <xsd:sequence> + <xsd:element name="caption" type="CT_Caption" minOccurs="1" maxOccurs="unbounded"/> + <xsd:element name="autoCaptions" type="CT_AutoCaptions" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_DocumentBase"> + <xsd:sequence> + <xsd:element name="background" type="CT_Background" minOccurs="0"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="CT_Document"> + <xsd:complexContent> + <xsd:extension base="CT_DocumentBase"> + <xsd:sequence> + <xsd:element name="body" type="CT_Body" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="conformance" type="s:ST_ConformanceClass"/> + <xsd:attribute ref="mc:Ignorable" use="optional" /> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:complexType name="CT_GlossaryDocument"> + <xsd:complexContent> + <xsd:extension base="CT_DocumentBase"> + <xsd:sequence> + <xsd:element name="docParts" type="CT_DocParts" minOccurs="0"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="document" type="CT_Document"/> + <xsd:element name="glossaryDocument" type="CT_GlossaryDocument"/> +</xsd:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd new file mode 100644 index 0000000..0f13678 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd @@ -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: + <schema . . .> + . . . + <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. + + <type . . .> + . . . + <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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd new file mode 100644 index 0000000..a6de9d2 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd @@ -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}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}\(\)<>@,;:\\"/\[\]\?=\{\}\s\t]])+)|("(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}"\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*"))))*)" + /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="ST_Extension"> + <xs:restriction base="xs:string"> + <xs:pattern + value="([!$&'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:@]|[a-zA-Z0-9\-_~])+"/> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd new file mode 100644 index 0000000..10e978b --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd new file mode 100644 index 0000000..4248bf7 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd new file mode 100644 index 0000000..5649746 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/mce/mc.xsd b/account/admin/skills/xlsx/scripts/office/schemas/mce/mc.xsd new file mode 100644 index 0000000..ef72545 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/mce/mc.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd new file mode 100644 index 0000000..f65f777 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd new file mode 100644 index 0000000..6b00755 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd new file mode 100644 index 0000000..f321d33 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd new file mode 100644 index 0000000..364c6a9 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd new file mode 100644 index 0000000..fed9d15 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd new file mode 100644 index 0000000..680cf15 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd new file mode 100644 index 0000000..89ada90 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd @@ -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> diff --git a/account/admin/skills/xlsx/scripts/office/soffice.py b/account/admin/skills/xlsx/scripts/office/soffice.py new file mode 100644 index 0000000..c7f7e32 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/soffice.py @@ -0,0 +1,183 @@ +""" +Helper for running LibreOffice (soffice) in environments where AF_UNIX +sockets may be blocked (e.g., sandboxed VMs). Detects the restriction +at runtime and applies an LD_PRELOAD shim if needed. + +Usage: + from office.soffice import run_soffice, get_soffice_env + + # Option 1 – run soffice directly + result = run_soffice(["--headless", "--convert-to", "pdf", "input.docx"]) + + # Option 2 – get env dict for your own subprocess calls + env = get_soffice_env() + subprocess.run(["soffice", ...], env=env) +""" + +import os +import socket +import subprocess +import tempfile +from pathlib import Path + + +def get_soffice_env() -> dict: + env = os.environ.copy() + env["SAL_USE_VCLPLUGIN"] = "svp" + + if _needs_shim(): + shim = _ensure_shim() + env["LD_PRELOAD"] = str(shim) + + return env + + +def run_soffice(args: list[str], **kwargs) -> subprocess.CompletedProcess: + env = get_soffice_env() + return subprocess.run(["soffice"] + args, env=env, **kwargs) + + + +_SHIM_SO = Path(tempfile.gettempdir()) / "lo_socket_shim.so" + + +def _needs_shim() -> bool: + try: + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.close() + return False + except OSError: + return True + + +def _ensure_shim() -> Path: + if _SHIM_SO.exists(): + return _SHIM_SO + + src = Path(tempfile.gettempdir()) / "lo_socket_shim.c" + src.write_text(_SHIM_SOURCE) + subprocess.run( + ["gcc", "-shared", "-fPIC", "-o", str(_SHIM_SO), str(src), "-ldl"], + check=True, + capture_output=True, + ) + src.unlink() + return _SHIM_SO + + + +_SHIM_SOURCE = r""" +#define _GNU_SOURCE +#include <dlfcn.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <unistd.h> + +static int (*real_socket)(int, int, int); +static int (*real_socketpair)(int, int, int, int[2]); +static int (*real_listen)(int, int); +static int (*real_accept)(int, struct sockaddr *, socklen_t *); +static int (*real_close)(int); +static int (*real_read)(int, void *, size_t); + +/* Per-FD bookkeeping (FDs >= 1024 are passed through unshimmed). */ +static int is_shimmed[1024]; +static int peer_of[1024]; +static int wake_r[1024]; /* accept() blocks reading this */ +static int wake_w[1024]; /* close() writes to this */ +static int listener_fd = -1; /* FD that received listen() */ + +__attribute__((constructor)) +static void init(void) { + real_socket = dlsym(RTLD_NEXT, "socket"); + real_socketpair = dlsym(RTLD_NEXT, "socketpair"); + real_listen = dlsym(RTLD_NEXT, "listen"); + real_accept = dlsym(RTLD_NEXT, "accept"); + real_close = dlsym(RTLD_NEXT, "close"); + real_read = dlsym(RTLD_NEXT, "read"); + for (int i = 0; i < 1024; i++) { + peer_of[i] = -1; + wake_r[i] = -1; + wake_w[i] = -1; + } +} + +/* ---- socket ---------------------------------------------------------- */ +int socket(int domain, int type, int protocol) { + if (domain == AF_UNIX) { + int fd = real_socket(domain, type, protocol); + if (fd >= 0) return fd; + /* socket(AF_UNIX) blocked – fall back to socketpair(). */ + int sv[2]; + if (real_socketpair(domain, type, protocol, sv) == 0) { + if (sv[0] >= 0 && sv[0] < 1024) { + is_shimmed[sv[0]] = 1; + peer_of[sv[0]] = sv[1]; + int wp[2]; + if (pipe(wp) == 0) { + wake_r[sv[0]] = wp[0]; + wake_w[sv[0]] = wp[1]; + } + } + return sv[0]; + } + errno = EPERM; + return -1; + } + return real_socket(domain, type, protocol); +} + +/* ---- listen ---------------------------------------------------------- */ +int listen(int sockfd, int backlog) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + listener_fd = sockfd; + return 0; + } + return real_listen(sockfd, backlog); +} + +/* ---- accept ---------------------------------------------------------- */ +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { + if (sockfd >= 0 && sockfd < 1024 && is_shimmed[sockfd]) { + /* Block until close() writes to the wake pipe. */ + if (wake_r[sockfd] >= 0) { + char buf; + real_read(wake_r[sockfd], &buf, 1); + } + errno = ECONNABORTED; + return -1; + } + return real_accept(sockfd, addr, addrlen); +} + +/* ---- close ----------------------------------------------------------- */ +int close(int fd) { + if (fd >= 0 && fd < 1024 && is_shimmed[fd]) { + int was_listener = (fd == listener_fd); + is_shimmed[fd] = 0; + + if (wake_w[fd] >= 0) { /* unblock accept() */ + char c = 0; + write(wake_w[fd], &c, 1); + real_close(wake_w[fd]); + wake_w[fd] = -1; + } + if (wake_r[fd] >= 0) { real_close(wake_r[fd]); wake_r[fd] = -1; } + if (peer_of[fd] >= 0) { real_close(peer_of[fd]); peer_of[fd] = -1; } + + if (was_listener) + _exit(0); /* conversion done – exit */ + } + return real_close(fd); +} +""" + + + +if __name__ == "__main__": + import sys + result = run_soffice(sys.argv[1:]) + sys.exit(result.returncode) diff --git a/account/admin/skills/xlsx/scripts/office/unpack.py b/account/admin/skills/xlsx/scripts/office/unpack.py new file mode 100644 index 0000000..0015253 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/unpack.py @@ -0,0 +1,132 @@ +"""Unpack Office files (DOCX, PPTX, XLSX) for editing. + +Extracts the ZIP archive, pretty-prints XML files, and optionally: +- Merges adjacent runs with identical formatting (DOCX only) +- Simplifies adjacent tracked changes from same author (DOCX only) + +Usage: + python unpack.py <office_file> <output_dir> [options] + +Examples: + python unpack.py document.docx unpacked/ + python unpack.py presentation.pptx unpacked/ + python unpack.py document.docx unpacked/ --merge-runs false +""" + +import argparse +import sys +import zipfile +from pathlib import Path + +import defusedxml.minidom + +from helpers.merge_runs import merge_runs as do_merge_runs +from helpers.simplify_redlines import simplify_redlines as do_simplify_redlines + +SMART_QUOTE_REPLACEMENTS = { + "\u201c": "“", + "\u201d": "”", + "\u2018": "‘", + "\u2019": "’", +} + + +def unpack( + input_file: str, + output_directory: str, + merge_runs: bool = True, + simplify_redlines: bool = True, +) -> tuple[None, str]: + input_path = Path(input_file) + output_path = Path(output_directory) + suffix = input_path.suffix.lower() + + if not input_path.exists(): + return None, f"Error: {input_file} does not exist" + + if suffix not in {".docx", ".pptx", ".xlsx"}: + return None, f"Error: {input_file} must be a .docx, .pptx, or .xlsx file" + + try: + output_path.mkdir(parents=True, exist_ok=True) + + with zipfile.ZipFile(input_path, "r") as zf: + zf.extractall(output_path) + + xml_files = list(output_path.rglob("*.xml")) + list(output_path.rglob("*.rels")) + for xml_file in xml_files: + _pretty_print_xml(xml_file) + + message = f"Unpacked {input_file} ({len(xml_files)} XML files)" + + if suffix == ".docx": + if simplify_redlines: + simplify_count, _ = do_simplify_redlines(str(output_path)) + message += f", simplified {simplify_count} tracked changes" + + if merge_runs: + merge_count, _ = do_merge_runs(str(output_path)) + message += f", merged {merge_count} runs" + + for xml_file in xml_files: + _escape_smart_quotes(xml_file) + + return None, message + + except zipfile.BadZipFile: + return None, f"Error: {input_file} is not a valid Office file" + except Exception as e: + return None, f"Error unpacking: {e}" + + +def _pretty_print_xml(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + xml_file.write_bytes(dom.toprettyxml(indent=" ", encoding="utf-8")) + except Exception: + pass + + +def _escape_smart_quotes(xml_file: Path) -> None: + try: + content = xml_file.read_text(encoding="utf-8") + for char, entity in SMART_QUOTE_REPLACEMENTS.items(): + content = content.replace(char, entity) + xml_file.write_text(content, encoding="utf-8") + except Exception: + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Unpack an Office file (DOCX, PPTX, XLSX) for editing" + ) + parser.add_argument("input_file", help="Office file to unpack") + parser.add_argument("output_directory", help="Output directory") + parser.add_argument( + "--merge-runs", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent runs with identical formatting (DOCX only, default: true)", + ) + parser.add_argument( + "--simplify-redlines", + type=lambda x: x.lower() == "true", + default=True, + metavar="true|false", + help="Merge adjacent tracked changes from same author (DOCX only, default: true)", + ) + args = parser.parse_args() + + _, message = unpack( + args.input_file, + args.output_directory, + merge_runs=args.merge_runs, + simplify_redlines=args.simplify_redlines, + ) + print(message) + + if "Error" in message: + sys.exit(1) diff --git a/account/admin/skills/xlsx/scripts/office/validate.py b/account/admin/skills/xlsx/scripts/office/validate.py new file mode 100644 index 0000000..03b01f6 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validate.py @@ -0,0 +1,111 @@ +""" +Command line tool to validate Office document XML files against XSD schemas and tracked changes. + +Usage: + python validate.py <path> [--original <original_file>] [--auto-repair] [--author NAME] + +The first argument can be either: +- An unpacked directory containing the Office document XML files +- A packed Office file (.docx/.pptx/.xlsx) which will be unpacked to a temp directory + +Auto-repair fixes: +- paraId/durableId values that exceed OOXML limits +- Missing xml:space="preserve" on w:t elements with whitespace +""" + +import argparse +import sys +import tempfile +import zipfile +from pathlib import Path + +from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator + + +def main(): + parser = argparse.ArgumentParser(description="Validate Office document XML files") + parser.add_argument( + "path", + help="Path to unpacked directory or packed Office file (.docx/.pptx/.xlsx)", + ) + parser.add_argument( + "--original", + required=False, + default=None, + help="Path to original file (.docx/.pptx/.xlsx). If omitted, all XSD errors are reported and redlining validation is skipped.", + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Enable verbose output", + ) + parser.add_argument( + "--auto-repair", + action="store_true", + help="Automatically repair common issues (hex IDs, whitespace preservation)", + ) + parser.add_argument( + "--author", + default="Claude", + help="Author name for redlining validation (default: Claude)", + ) + args = parser.parse_args() + + path = Path(args.path) + assert path.exists(), f"Error: {path} does not exist" + + original_file = None + if args.original: + original_file = Path(args.original) + assert original_file.is_file(), f"Error: {original_file} is not a file" + assert original_file.suffix.lower() in [".docx", ".pptx", ".xlsx"], ( + f"Error: {original_file} must be a .docx, .pptx, or .xlsx file" + ) + + file_extension = (original_file or path).suffix.lower() + assert file_extension in [".docx", ".pptx", ".xlsx"], ( + f"Error: Cannot determine file type from {path}. Use --original or provide a .docx/.pptx/.xlsx file." + ) + + if path.is_file() and path.suffix.lower() in [".docx", ".pptx", ".xlsx"]: + temp_dir = tempfile.mkdtemp() + with zipfile.ZipFile(path, "r") as zf: + zf.extractall(temp_dir) + unpacked_dir = Path(temp_dir) + else: + assert path.is_dir(), f"Error: {path} is not a directory or Office file" + unpacked_dir = path + + match file_extension: + case ".docx": + validators = [ + DOCXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + if original_file: + validators.append( + RedliningValidator(unpacked_dir, original_file, verbose=args.verbose, author=args.author) + ) + case ".pptx": + validators = [ + PPTXSchemaValidator(unpacked_dir, original_file, verbose=args.verbose), + ] + case _: + print(f"Error: Validation not supported for file type {file_extension}") + sys.exit(1) + + if args.auto_repair: + total_repairs = sum(v.repair() for v in validators) + if total_repairs: + print(f"Auto-repaired {total_repairs} issue(s)") + + success = all(v.validate() for v in validators) + + if success: + print("All validations PASSED!") + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/xlsx/scripts/office/validators/__init__.py b/account/admin/skills/xlsx/scripts/office/validators/__init__.py new file mode 100644 index 0000000..db092ec --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validators/__init__.py @@ -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", +] diff --git a/account/admin/skills/xlsx/scripts/office/validators/base.py b/account/admin/skills/xlsx/scripts/office/validators/base.py new file mode 100644 index 0000000..db4a06a --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validators/base.py @@ -0,0 +1,847 @@ +""" +Base validator with common validation logic for document files. +""" + +import re +from pathlib import Path + +import defusedxml.minidom +import lxml.etree + + +class BaseSchemaValidator: + + IGNORED_VALIDATION_ERRORS = [ + "hyphenationZone", + "purl.org/dc/terms", + ] + + UNIQUE_ID_REQUIREMENTS = { + "comment": ("id", "file"), + "commentrangestart": ("id", "file"), + "commentrangeend": ("id", "file"), + "bookmarkstart": ("id", "file"), + "bookmarkend": ("id", "file"), + "sldid": ("id", "file"), + "sldmasterid": ("id", "global"), + "sldlayoutid": ("id", "global"), + "cm": ("authorid", "file"), + "sheet": ("sheetid", "file"), + "definedname": ("id", "file"), + "cxnsp": ("id", "file"), + "sp": ("id", "file"), + "pic": ("id", "file"), + "grpsp": ("id", "file"), + } + + EXCLUDED_ID_CONTAINERS = { + "sectionlst", + } + + ELEMENT_RELATIONSHIP_TYPES = {} + + SCHEMA_MAPPINGS = { + "word": "ISO-IEC29500-4_2016/wml.xsd", + "ppt": "ISO-IEC29500-4_2016/pml.xsd", + "xl": "ISO-IEC29500-4_2016/sml.xsd", + "[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", + "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": "ISO-IEC29500-4_2016/dml-chart.xsd", + "theme": "ISO-IEC29500-4_2016/dml-main.xsd", + "drawing": "ISO-IEC29500-4_2016/dml-main.xsd", + } + + MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006" + XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" + + 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" + ) + + MAIN_CONTENT_FOLDERS = {"word", "ppt", "xl"} + + 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=None, verbose=False): + self.unpacked_dir = Path(unpacked_dir).resolve() + self.original_file = Path(original_file) if original_file else None + self.verbose = verbose + + self.schemas_dir = Path(__file__).parent.parent / "schemas" + + 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): + raise NotImplementedError("Subclasses must implement the validate method") + + def repair(self) -> int: + return self.repair_whitespace_preservation() + + def repair_whitespace_preservation(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if elem.tagName.endswith(":t") and elem.firstChild: + text = elem.firstChild.nodeValue + if text and (text.startswith((' ', '\t')) or text.endswith((' ', '\t'))): + if elem.getAttribute("xml:space") != "preserve": + elem.setAttribute("xml:space", "preserve") + text_preview = repr(text[:30]) + "..." if len(text) > 30 else repr(text) + print(f" Repaired: {xml_file.name}: Added xml:space='preserve' to {elem.tagName}: {text_preview}") + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + def validate_xml(self): + errors = [] + + for xml_file in self.xml_files: + try: + 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): + errors = [] + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + declared = set(root.nsmap.keys()) - {None} + + 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): + errors = [] + global_ids = {} + + for xml_file in self.xml_files: + try: + root = lxml.etree.parse(str(xml_file)).getroot() + file_ids = {} + + mc_elements = root.xpath( + ".//mc:AlternateContent", namespaces={"mc": self.MC_NAMESPACE} + ) + for elem in mc_elements: + elem.getparent().remove(elem) + + for elem in root.iter(): + tag = ( + elem.tag.split("}")[-1].lower() + if "}" in elem.tag + else elem.tag.lower() + ) + + if tag in self.UNIQUE_ID_REQUIREMENTS: + in_excluded_container = any( + ancestor.tag.split("}")[-1].lower() in self.EXCLUDED_ID_CONTAINERS + for ancestor in elem.iterancestors() + ) + if in_excluded_container: + continue + + attr_name, scope = self.UNIQUE_ID_REQUIREMENTS[tag] + + 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": + 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": + 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): + errors = [] + + rels_files = list(self.unpacked_dir.rglob("*.rels")) + + if not rels_files: + if self.verbose: + print("PASSED - No .rels files found") + return True + + 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") + ): + all_files.append(file_path.resolve()) + + all_referenced_files = set() + + if self.verbose: + print( + f"Found {len(rels_files)} .rels files and {len(all_files)} target files" + ) + + for rels_file in rels_files: + try: + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + rels_dir = rels_file.parent + + 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:") + ): + if target.startswith("/"): + target_path = self.unpacked_dir / target.lstrip("/") + elif rels_file.name == ".rels": + target_path = self.unpacked_dir / target + else: + base_dir = rels_dir.parent + target_path = base_dir / target + + 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)) + + 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}") + + 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): + import lxml.etree + + errors = [] + + for xml_file in self.xml_files: + if xml_file.suffix == ".rels": + continue + + rels_dir = xml_file.parent / "_rels" + rels_file = rels_dir / f"{xml_file.name}.rels" + + if not rels_file.exists(): + continue + + try: + 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: + 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)" + ) + type_name = ( + rel_type.split("/")[-1] if "/" in rel_type else rel_type + ) + rid_to_type[rid] = type_name + + xml_root = lxml.etree.parse(str(xml_file)).getroot() + + r_ns = self.OFFICE_RELATIONSHIPS_NAMESPACE + rid_attrs_to_check = ["id", "embed", "link"] + for elem in xml_root.iter(): + for attr_name in rid_attrs_to_check: + rid_attr = elem.get(f"{{{r_ns}}}{attr_name}") + if not rid_attr: + continue + xml_rel_path = xml_file.relative_to(self.unpacked_dir) + elem_name = ( + elem.tag.split("}")[-1] if "}" in elem.tag else elem.tag + ) + + if rid_attr not in rid_to_type: + errors.append( + f" {xml_rel_path}: Line {elem.sourceline}: " + f"<{elem_name}> r:{attr_name} references non-existent relationship '{rid_attr}' " + f"(valid IDs: {', '.join(sorted(rid_to_type.keys())[:5])}{'...' if len(rid_to_type) > 5 else ''})" + ) + elif attr_name == "id" and self.ELEMENT_RELATIONSHIP_TYPES: + expected_type = self._get_expected_relationship_type( + elem_name + ) + if expected_type: + actual_type = rid_to_type[rid_attr] + 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): + elem_lower = element_name.lower() + + if elem_lower in self.ELEMENT_RELATIONSHIP_TYPES: + return self.ELEMENT_RELATIONSHIP_TYPES[elem_lower] + + if elem_lower.endswith("id") and len(elem_lower) > 2: + prefix = elem_lower[:-2] + if prefix.endswith("master"): + return prefix.lower() + elif prefix.endswith("layout"): + return prefix.lower() + else: + if prefix == "sld": + return "slide" + return prefix.lower() + + if elem_lower.endswith("reference") and len(elem_lower) > 9: + prefix = elem_lower[:-9] + return prefix.lower() + + return None + + def validate_content_types(self): + errors = [] + + 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: + root = lxml.etree.parse(str(content_types_file)).getroot() + declared_parts = set() + declared_extensions = set() + + 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("/")) + + 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()) + + declarable_roots = { + "sld", + "sldLayout", + "sldMaster", + "presentation", + "document", + "workbook", + "worksheet", + "theme", + } + + 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", + } + + all_files = list(self.unpacked_dir.rglob("*")) + all_files = [f for f in all_files if f.is_file()] + + for xml_file in self.xml_files: + path_str = str(xml_file.relative_to(self.unpacked_dir)).replace( + "\\", "/" + ) + + 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 + + for file_path in all_files: + 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: + 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): + xml_file = Path(xml_file).resolve() + unpacked_dir = self.unpacked_dir.resolve() + + is_valid, current_errors = self._validate_single_file_xsd( + xml_file, unpacked_dir + ) + + if is_valid is None: + return None, set() + elif is_valid: + return True, set() + + original_errors = self._get_original_file_errors(xml_file) + + assert current_errors is not None + new_errors = current_errors - original_errors + + new_errors = { + e for e in new_errors + if not any(pattern in e for pattern in self.IGNORED_VALIDATION_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: + if verbose: + print( + f"PASSED - No new errors (original had {len(current_errors)} errors)" + ) + return True, set() + + def validate_against_xsd(self): + 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: + original_error_count += 1 + valid_count += 1 + continue + + new_errors.append(f" {relative_path}: {len(new_file_errors)} new error(s)") + for error in list(new_file_errors)[:3]: + new_errors.append( + f" - {error[:250]}..." if len(error) > 250 else f" - {error}" + ) + + 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): + if xml_file.name in self.SCHEMA_MAPPINGS: + return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.name] + + if xml_file.suffix == ".rels": + return self.schemas_dir / self.SCHEMA_MAPPINGS[".rels"] + + if "charts/" in str(xml_file) and xml_file.name.startswith("chart"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["chart"] + + if "theme/" in str(xml_file) and xml_file.name.startswith("theme"): + return self.schemas_dir / self.SCHEMA_MAPPINGS["theme"] + + 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): + xml_string = lxml.etree.tostring(xml_doc, encoding="unicode") + xml_copy = lxml.etree.fromstring(xml_string) + + for elem in xml_copy.iter(): + attrs_to_remove = [] + + for attr in elem.attrib: + if "{" in attr: + ns = attr.split("}")[0][1:] + if ns not in self.OOXML_NAMESPACES: + attrs_to_remove.append(attr) + + for attr in attrs_to_remove: + del elem.attrib[attr] + + self._remove_ignorable_elements(xml_copy) + + return lxml.etree.ElementTree(xml_copy) + + def _remove_ignorable_elements(self, root): + elements_to_remove = [] + + for elem in list(root): + 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 + + self._remove_ignorable_elements(elem) + + for elem in elements_to_remove: + root.remove(elem) + + def _preprocess_for_mc_ignorable(self, xml_doc): + root = xml_doc.getroot() + + 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): + schema_path = self._get_schema_path(xml_file) + if not schema_path: + return None, None + + try: + 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) + + 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) + + 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) + + if schema.validate(xml_doc): + return True, set() + else: + errors = set() + for error in schema.error_log: + errors.add(error.message) + return False, errors + + except Exception as e: + return False, {str(e)} + + def _get_original_file_errors(self, xml_file): + if self.original_file is None: + return set() + + import tempfile + import zipfile + + 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) + + with zipfile.ZipFile(self.original_file, "r") as zip_ref: + zip_ref.extractall(temp_path) + + original_xml_file = temp_path / relative_path + + if not original_xml_file.exists(): + return set() + + 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): + warnings = [] + template_pattern = re.compile(r"\{\{[^}]*\}\}") + + 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 + + for elem in xml_copy.iter(): + 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.") diff --git a/account/admin/skills/xlsx/scripts/office/validators/docx.py b/account/admin/skills/xlsx/scripts/office/validators/docx.py new file mode 100644 index 0000000..fec405e --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validators/docx.py @@ -0,0 +1,446 @@ +""" +Validator for Word document XML files against XSD schemas. +""" + +import random +import re +import tempfile +import zipfile + +import defusedxml.minidom +import lxml.etree + +from .base import BaseSchemaValidator + + +class DOCXSchemaValidator(BaseSchemaValidator): + + WORD_2006_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + W14_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml" + W16CID_NAMESPACE = "http://schemas.microsoft.com/office/word/2016/wordml/cid" + + ELEMENT_RELATIONSHIP_TYPES = {} + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_whitespace_preservation(): + all_valid = False + + if not self.validate_deletions(): + all_valid = False + + if not self.validate_insertions(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_id_constraints(): + all_valid = False + + if not self.validate_comment_markers(): + all_valid = False + + self.compare_paragraph_counts() + + return all_valid + + def validate_whitespace_preservation(self): + errors = [] + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + + for elem in root.iter(f"{{{self.WORD_2006_NAMESPACE}}}t"): + if elem.text: + text = elem.text + if re.search(r"^[ \t\n\r]", text) or re.search( + r"[ \t\n\r]$", text + ): + xml_space_attr = f"{{{self.XML_NAMESPACE}}}space" + if ( + xml_space_attr not in elem.attrib + or elem.attrib[xml_space_attr] != "preserve" + ): + 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): + 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} + + for t_elem in root.xpath(".//w:del//w:t", namespaces=namespaces): + if t_elem.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}" + ) + + for instr_elem in root.xpath( + ".//w:del//w:instrText", namespaces=namespaces + ): + text_preview = ( + repr(instr_elem.text or "")[:50] + "..." + if len(repr(instr_elem.text or "")) > 50 + else repr(instr_elem.text or "") + ) + errors.append( + f" {xml_file.relative_to(self.unpacked_dir)}: " + f"Line {instr_elem.sourceline}: <w:instrText> found within <w:del> (use <w:delInstrText>): {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 = 0 + + for xml_file in self.xml_files: + if xml_file.name != "document.xml": + continue + + try: + root = lxml.etree.parse(str(xml_file)).getroot() + 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): + original = self.original_file + if original is None: + return 0 + + count = 0 + + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(original, "r") as zip_ref: + zip_ref.extractall(temp_dir) + + doc_xml_path = temp_dir + "/word/document.xml" + root = lxml.etree.parse(doc_xml_path).getroot() + + 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): + 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} + + 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): + 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})") + + def _parse_id_value(self, val: str, base: int = 16) -> int: + return int(val, base) + + def validate_id_constraints(self): + errors = [] + para_id_attr = f"{{{self.W14_NAMESPACE}}}paraId" + durable_id_attr = f"{{{self.W16CID_NAMESPACE}}}durableId" + + for xml_file in self.xml_files: + try: + for elem in lxml.etree.parse(str(xml_file)).iter(): + if val := elem.get(para_id_attr): + if self._parse_id_value(val, base=16) >= 0x80000000: + errors.append( + f" {xml_file.name}:{elem.sourceline}: paraId={val} >= 0x80000000" + ) + + if val := elem.get(durable_id_attr): + if xml_file.name == "numbering.xml": + try: + if self._parse_id_value(val, base=10) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except ValueError: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} must be decimal in numbering.xml" + ) + else: + if self._parse_id_value(val, base=16) >= 0x7FFFFFFF: + errors.append( + f" {xml_file.name}:{elem.sourceline}: " + f"durableId={val} >= 0x7FFFFFFF" + ) + except Exception: + pass + + if errors: + print(f"FAILED - {len(errors)} ID constraint violations:") + for e in errors: + print(e) + elif self.verbose: + print("PASSED - All paraId/durableId values within constraints") + return not errors + + def validate_comment_markers(self): + errors = [] + + document_xml = None + comments_xml = None + for xml_file in self.xml_files: + if xml_file.name == "document.xml" and "word" in str(xml_file): + document_xml = xml_file + elif xml_file.name == "comments.xml": + comments_xml = xml_file + + if not document_xml: + if self.verbose: + print("PASSED - No document.xml found (skipping comment validation)") + return True + + try: + doc_root = lxml.etree.parse(str(document_xml)).getroot() + namespaces = {"w": self.WORD_2006_NAMESPACE} + + range_starts = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeStart", namespaces=namespaces + ) + } + range_ends = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentRangeEnd", namespaces=namespaces + ) + } + references = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in doc_root.xpath( + ".//w:commentReference", namespaces=namespaces + ) + } + + orphaned_ends = range_ends - range_starts + for comment_id in sorted( + orphaned_ends, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeEnd id="{comment_id}" has no matching commentRangeStart' + ) + + orphaned_starts = range_starts - range_ends + for comment_id in sorted( + orphaned_starts, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + errors.append( + f' document.xml: commentRangeStart id="{comment_id}" has no matching commentRangeEnd' + ) + + comment_ids = set() + if comments_xml and comments_xml.exists(): + comments_root = lxml.etree.parse(str(comments_xml)).getroot() + comment_ids = { + elem.get(f"{{{self.WORD_2006_NAMESPACE}}}id") + for elem in comments_root.xpath( + ".//w:comment", namespaces=namespaces + ) + } + + marker_ids = range_starts | range_ends | references + invalid_refs = marker_ids - comment_ids + for comment_id in sorted( + invalid_refs, key=lambda x: int(x) if x and x.isdigit() else 0 + ): + if comment_id: + errors.append( + f' document.xml: marker id="{comment_id}" references non-existent comment' + ) + + except (lxml.etree.XMLSyntaxError, Exception) as e: + errors.append(f" Error parsing XML: {e}") + + if errors: + print(f"FAILED - {len(errors)} comment marker violations:") + for error in errors: + print(error) + return False + else: + if self.verbose: + print("PASSED - All comment markers properly paired") + return True + + def repair(self) -> int: + repairs = super().repair() + repairs += self.repair_durableId() + return repairs + + def repair_durableId(self) -> int: + repairs = 0 + + for xml_file in self.xml_files: + try: + content = xml_file.read_text(encoding="utf-8") + dom = defusedxml.minidom.parseString(content) + modified = False + + for elem in dom.getElementsByTagName("*"): + if not elem.hasAttribute("w16cid:durableId"): + continue + + durable_id = elem.getAttribute("w16cid:durableId") + needs_repair = False + + if xml_file.name == "numbering.xml": + try: + needs_repair = ( + self._parse_id_value(durable_id, base=10) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + else: + try: + needs_repair = ( + self._parse_id_value(durable_id, base=16) >= 0x7FFFFFFF + ) + except ValueError: + needs_repair = True + + if needs_repair: + value = random.randint(1, 0x7FFFFFFE) + if xml_file.name == "numbering.xml": + new_id = str(value) + else: + new_id = f"{value:08X}" + + elem.setAttribute("w16cid:durableId", new_id) + print( + f" Repaired: {xml_file.name}: durableId {durable_id} → {new_id}" + ) + repairs += 1 + modified = True + + if modified: + xml_file.write_bytes(dom.toxml(encoding="UTF-8")) + + except Exception: + pass + + return repairs + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/account/admin/skills/xlsx/scripts/office/validators/pptx.py b/account/admin/skills/xlsx/scripts/office/validators/pptx.py new file mode 100644 index 0000000..09842aa --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validators/pptx.py @@ -0,0 +1,275 @@ +""" +Validator for PowerPoint presentation XML files against XSD schemas. +""" + +import re + +from .base import BaseSchemaValidator + + +class PPTXSchemaValidator(BaseSchemaValidator): + + PRESENTATIONML_NAMESPACE = ( + "http://schemas.openxmlformats.org/presentationml/2006/main" + ) + + ELEMENT_RELATIONSHIP_TYPES = { + "sldid": "slide", + "sldmasterid": "slidemaster", + "notesmasterid": "notesmaster", + "sldlayoutid": "slidelayout", + "themeid": "theme", + "tablestyleid": "tablestyles", + } + + def validate(self): + if not self.validate_xml(): + return False + + all_valid = True + if not self.validate_namespaces(): + all_valid = False + + if not self.validate_unique_ids(): + all_valid = False + + if not self.validate_uuid_ids(): + all_valid = False + + if not self.validate_file_references(): + all_valid = False + + if not self.validate_slide_layout_ids(): + all_valid = False + + if not self.validate_content_types(): + all_valid = False + + if not self.validate_against_xsd(): + all_valid = False + + if not self.validate_notes_slide_references(): + all_valid = False + + if not self.validate_all_relationship_ids(): + all_valid = False + + if not self.validate_no_duplicate_slide_layouts(): + all_valid = False + + return all_valid + + def validate_uuid_ids(self): + import lxml.etree + + errors = [] + 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() + + for elem in root.iter(): + for attr, value in elem.attrib.items(): + attr_name = attr.split("}")[-1].lower() + if attr_name == "id" or attr_name.endswith("id"): + if self._looks_like_uuid(value): + 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): + clean_value = value.strip("{}()").replace("-", "") + return len(clean_value) == 32 and all(c.isalnum() for c in clean_value) + + def validate_slide_layout_ids(self): + import lxml.etree + + errors = [] + + 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: + root = lxml.etree.parse(str(slide_master)).getroot() + + 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 + + rels_root = lxml.etree.parse(str(rels_file)).getroot() + + 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")) + + 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): + import lxml.etree + + 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() + + 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): + import lxml.etree + + errors = [] + notes_slide_references = {} + + 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: + root = lxml.etree.parse(str(rels_file)).getroot() + + 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: + normalized_target = target.replace("../", "") + + slide_name = rels_file.stem.replace( + ".xml", "" + ) + + 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}" + ) + + 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.") diff --git a/account/admin/skills/xlsx/scripts/office/validators/redlining.py b/account/admin/skills/xlsx/scripts/office/validators/redlining.py new file mode 100644 index 0000000..71c81b6 --- /dev/null +++ b/account/admin/skills/xlsx/scripts/office/validators/redlining.py @@ -0,0 +1,247 @@ +""" +Validator for tracked changes in Word documents. +""" + +import subprocess +import tempfile +import zipfile +from pathlib import Path + + +class RedliningValidator: + + def __init__(self, unpacked_dir, original_docx, verbose=False, author="Claude"): + self.unpacked_dir = Path(unpacked_dir) + self.original_docx = Path(original_docx) + self.verbose = verbose + self.author = author + self.namespaces = { + "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + } + + def repair(self) -> int: + return 0 + + def validate(self): + 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 + + try: + import xml.etree.ElementTree as ET + + tree = ET.parse(modified_file) + root = tree.getroot() + + del_elements = root.findall(".//w:del", self.namespaces) + ins_elements = root.findall(".//w:ins", self.namespaces) + + author_del_elements = [ + elem + for elem in del_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + author_ins_elements = [ + elem + for elem in ins_elements + if elem.get(f"{{{self.namespaces['w']}}}author") == self.author + ] + + if not author_del_elements and not author_ins_elements: + if self.verbose: + print(f"PASSED - No tracked changes by {self.author} found.") + return True + + except Exception: + pass + + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + 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 + + 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 + + self._remove_author_tracked_changes(original_root) + self._remove_author_tracked_changes(modified_root) + + modified_text = self._extract_text_content(modified_root) + original_text = self._extract_text_content(original_root) + + if modified_text != original_text: + error_message = self._generate_detailed_diff( + original_text, modified_text + ) + print(error_message) + return False + + if self.verbose: + print(f"PASSED - All changes by {self.author} are properly tracked") + return True + + def _generate_detailed_diff(self, original_text, modified_text): + error_parts = [ + f"FAILED - Document text doesn't match after removing {self.author}'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>", + "", + ] + + 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): + try: + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + 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") + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "--word-diff-regex=.", + "-U0", + "--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) + + if content_lines: + return "\n".join(content_lines) + + result = subprocess.run( + [ + "git", + "diff", + "--word-diff=plain", + "-U0", + "--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): + pass + + return None + + def _remove_author_tracked_changes(self, root): + ins_tag = f"{{{self.namespaces['w']}}}ins" + del_tag = f"{{{self.namespaces['w']}}}del" + author_attr = f"{{{self.namespaces['w']}}}author" + + for parent in root.iter(): + to_remove = [] + for child in parent: + if child.tag == ins_tag and child.get(author_attr) == self.author: + to_remove.append(child) + for elem in to_remove: + parent.remove(elem) + + 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) == self.author: + to_process.append((child, list(parent).index(child))) + + for del_elem, del_index in reversed(to_process): + for elem in del_elem.iter(): + if elem.tag == deltext_tag: + elem.tag = t_tag + + for child in reversed(list(del_elem)): + parent.insert(del_index, child) + parent.remove(del_elem) + + def _extract_text_content(self, root): + p_tag = f"{{{self.namespaces['w']}}}p" + t_tag = f"{{{self.namespaces['w']}}}t" + + paragraphs = [] + for p_elem in root.findall(f".//{p_tag}"): + 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) + if paragraph_text: + paragraphs.append(paragraph_text) + + return "\n".join(paragraphs) + + +if __name__ == "__main__": + raise RuntimeError("This module should not be run directly.") diff --git a/account/admin/skills/xlsx/scripts/recalc.py b/account/admin/skills/xlsx/scripts/recalc.py new file mode 100644 index 0000000..f472e9a --- /dev/null +++ b/account/admin/skills/xlsx/scripts/recalc.py @@ -0,0 +1,184 @@ +""" +Excel Formula Recalculation Script +Recalculates all formulas in an Excel file using LibreOffice +""" + +import json +import os +import platform +import subprocess +import sys +from pathlib import Path + +from office.soffice import get_soffice_env + +from openpyxl import load_workbook + +MACRO_DIR_MACOS = "~/Library/Application Support/LibreOffice/4/user/basic/Standard" +MACRO_DIR_LINUX = "~/.config/libreoffice/4/user/basic/Standard" +MACRO_FILENAME = "Module1.xba" + +RECALCULATE_MACRO = """<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd"> +<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic"> + Sub RecalculateAndSave() + ThisComponent.calculateAll() + ThisComponent.store() + ThisComponent.close(True) + End Sub +</script:module>""" + + +def has_gtimeout(): + try: + subprocess.run( + ["gtimeout", "--version"], capture_output=True, timeout=1, check=False + ) + return True + except (FileNotFoundError, subprocess.TimeoutExpired): + return False + + +def setup_libreoffice_macro(): + macro_dir = os.path.expanduser( + MACRO_DIR_MACOS if platform.system() == "Darwin" else MACRO_DIR_LINUX + ) + macro_file = os.path.join(macro_dir, MACRO_FILENAME) + + if ( + os.path.exists(macro_file) + and "RecalculateAndSave" in Path(macro_file).read_text() + ): + return True + + if not os.path.exists(macro_dir): + subprocess.run( + ["soffice", "--headless", "--terminate_after_init"], + capture_output=True, + timeout=10, + env=get_soffice_env(), + ) + os.makedirs(macro_dir, exist_ok=True) + + try: + Path(macro_file).write_text(RECALCULATE_MACRO) + return True + except Exception: + return False + + +def recalc(filename, timeout=30): + if not Path(filename).exists(): + return {"error": f"File {filename} does not exist"} + + abs_path = str(Path(filename).absolute()) + + if not setup_libreoffice_macro(): + return {"error": "Failed to setup LibreOffice macro"} + + cmd = [ + "soffice", + "--headless", + "--norestore", + "vnd.sun.star.script:Standard.Module1.RecalculateAndSave?language=Basic&location=application", + abs_path, + ] + + if platform.system() == "Linux": + cmd = ["timeout", str(timeout)] + cmd + elif platform.system() == "Darwin" and has_gtimeout(): + cmd = ["gtimeout", str(timeout)] + cmd + + result = subprocess.run(cmd, capture_output=True, text=True, env=get_soffice_env()) + + if result.returncode != 0 and result.returncode != 124: + error_msg = result.stderr or "Unknown error during recalculation" + if "Module1" in error_msg or "RecalculateAndSave" not in error_msg: + return {"error": "LibreOffice macro not configured properly"} + return {"error": error_msg} + + try: + wb = load_workbook(filename, data_only=True) + + excel_errors = [ + "#VALUE!", + "#DIV/0!", + "#REF!", + "#NAME?", + "#NULL!", + "#NUM!", + "#N/A", + ] + error_details = {err: [] for err in excel_errors} + total_errors = 0 + + for sheet_name in wb.sheetnames: + ws = wb[sheet_name] + for row in ws.iter_rows(): + for cell in row: + if cell.value is not None and isinstance(cell.value, str): + for err in excel_errors: + if err in cell.value: + location = f"{sheet_name}!{cell.coordinate}" + error_details[err].append(location) + total_errors += 1 + break + + wb.close() + + result = { + "status": "success" if total_errors == 0 else "errors_found", + "total_errors": total_errors, + "error_summary": {}, + } + + for err_type, locations in error_details.items(): + if locations: + result["error_summary"][err_type] = { + "count": len(locations), + "locations": locations[:20], + } + + wb_formulas = load_workbook(filename, data_only=False) + formula_count = 0 + for sheet_name in wb_formulas.sheetnames: + ws = wb_formulas[sheet_name] + for row in ws.iter_rows(): + for cell in row: + if ( + cell.value + and isinstance(cell.value, str) + and cell.value.startswith("=") + ): + formula_count += 1 + wb_formulas.close() + + result["total_formulas"] = formula_count + + return result + + except Exception as e: + return {"error": str(e)} + + +def main(): + if len(sys.argv) < 2: + print("Usage: python recalc.py <excel_file> [timeout_seconds]") + print("\nRecalculates all formulas in an Excel file using LibreOffice") + print("\nReturns JSON with error details:") + print(" - status: 'success' or 'errors_found'") + print(" - total_errors: Total number of Excel errors found") + print(" - total_formulas: Number of formulas in the file") + print(" - error_summary: Breakdown by error type with locations") + print(" - #VALUE!, #DIV/0!, #REF!, #NAME?, #NULL!, #NUM!, #N/A") + sys.exit(1) + + filename = sys.argv[1] + timeout = int(sys.argv[2]) if len(sys.argv) > 2 else 30 + + result = recalc(filename, timeout) + print(json.dumps(result, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/account/admin/skills/youtube-summarizer/.openakita-i18n.json b/account/admin/skills/youtube-summarizer/.openakita-i18n.json new file mode 100644 index 0000000..e162c2d --- /dev/null +++ b/account/admin/skills/youtube-summarizer/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "YouTube 视频总结", + "description": "从 YouTube 视频中提取字幕并生成结构化摘要笔记,支持多种 URL 格式和语言,使用 STAR + R-I-S-E 框架输出要点、时间戳和详细笔记。" + } +} diff --git a/account/admin/skills/youtube-summarizer/SKILL.md b/account/admin/skills/youtube-summarizer/SKILL.md new file mode 100644 index 0000000..917af9f --- /dev/null +++ b/account/admin/skills/youtube-summarizer/SKILL.md @@ -0,0 +1,439 @@ +--- +name: openakita/skills@youtube-summarizer +description: Summarize YouTube videos by extracting transcripts and generating structured notes. Use when the user wants to summarize a YouTube video, extract key points from a talk, create study notes from a lecture, or get timestamps for important moments. Supports multiple URL formats and languages. +license: MIT +metadata: + author: openakita + version: "1.0.0" + based_on: sickn33/antigravity-awesome-skills/youtube-summarizer +--- + +# YouTube Video Summarizer + +Extract transcripts from YouTube videos and generate structured, actionable summaries using the **STAR + R-I-S-E** framework. + +## When to Use This Skill + +- User shares a YouTube link and asks "summarize this" or "what's this video about" +- User wants key takeaways or study notes from a lecture/talk +- User needs timestamped highlights from a long video +- User wants a structured breakdown of a tutorial or presentation +- User asks to compare content across multiple YouTube videos +- User wants to extract quotes or specific segments from a video + +## Prerequisites + +### Install Required Package + +```bash +pip install youtube-transcript-api +``` + +If pip is not available, try: + +```bash +pip3 install youtube-transcript-api +``` + +Verify installation: + +```python +from youtube_transcript_api import YouTubeTranscriptApi +print("youtube-transcript-api is ready") +``` + +### Supported Python Versions + +- Python 3.8+ +- No additional system dependencies required + +--- + +## Instructions + +### Step 1: Extract the Video ID + +YouTube URLs come in many formats. Parse all of them to extract the 11-character video ID: + +| URL Format | Example | Extraction | +|---|---|---| +| Standard | `https://www.youtube.com/watch?v=dQw4w9WgXcQ` | Query param `v` | +| Short | `https://youtu.be/dQw4w9WgXcQ` | Path segment | +| Embed | `https://www.youtube.com/embed/dQw4w9WgXcQ` | Path after `/embed/` | +| Live | `https://www.youtube.com/live/dQw4w9WgXcQ` | Path after `/live/` | +| Shorts | `https://www.youtube.com/shorts/dQw4w9WgXcQ` | Path after `/shorts/` | +| With timestamp | `https://youtu.be/dQw4w9WgXcQ?t=120` | Ignore query params | +| With playlist | `https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PLxx` | Use only `v` param | +| Mobile | `https://m.youtube.com/watch?v=dQw4w9WgXcQ` | Same as standard | +| Bare ID | `dQw4w9WgXcQ` | Use directly | + +```python +import re +from urllib.parse import urlparse, parse_qs + +def extract_video_id(url_or_id: str) -> str: + """Extract YouTube video ID from various URL formats.""" + url_or_id = url_or_id.strip() + + # Bare video ID (11 chars, alphanumeric + dash + underscore) + if re.match(r'^[A-Za-z0-9_-]{11}$', url_or_id): + return url_or_id + + parsed = urlparse(url_or_id) + + # youtu.be short links + if parsed.hostname in ('youtu.be',): + return parsed.path.lstrip('/') + + # Standard, mobile, embed, live, shorts + if parsed.hostname in ('www.youtube.com', 'youtube.com', 'm.youtube.com'): + if parsed.path == '/watch': + qs = parse_qs(parsed.query) + return qs.get('v', [None])[0] + for prefix in ('/embed/', '/live/', '/shorts/', '/v/'): + if parsed.path.startswith(prefix): + return parsed.path[len(prefix):].split('/')[0] + + raise ValueError(f"Cannot extract video ID from: {url_or_id}") +``` + +### Step 2: Fetch the Transcript + +```python +from youtube_transcript_api import YouTubeTranscriptApi + +def fetch_transcript(video_id: str, preferred_langs=None): + """ + Fetch transcript with language fallback. + + Args: + video_id: The 11-character YouTube video ID + preferred_langs: Ordered list of language codes, e.g. ['zh-Hans', 'zh', 'en'] + Defaults to ['en'] if not specified + + Returns: + List of transcript segments with 'text', 'start', 'duration' keys + """ + if preferred_langs is None: + preferred_langs = ['en'] + + try: + transcript_list = YouTubeTranscriptApi.list_transcripts(video_id) + + # Try manually created transcripts first (more accurate) + for lang in preferred_langs: + try: + transcript = transcript_list.find_manually_created_transcript([lang]) + return transcript.fetch() + except Exception: + continue + + # Fall back to auto-generated transcripts + for lang in preferred_langs: + try: + transcript = transcript_list.find_generated_transcript([lang]) + return transcript.fetch() + except Exception: + continue + + # Last resort: get any available transcript and translate + for transcript in transcript_list: + try: + if 'en' in preferred_langs: + return transcript.translate('en').fetch() + return transcript.fetch() + except Exception: + continue + + raise RuntimeError("No transcript available in any language") + + except Exception as e: + raise RuntimeError(f"Failed to fetch transcript for {video_id}: {e}") +``` + +### Step 3: Generate the Summary + +Use the **STAR + R-I-S-E** combined framework for maximum clarity: + +#### STAR Framework (for factual/process content) + +- **S**ituation — What context does the video establish? +- **T**ask — What problem or question is being addressed? +- **A**ction — What steps, methods, or arguments are presented? +- **R**esult — What conclusions, outcomes, or calls to action are given? + +#### R-I-S-E Framework (for opinion/analysis content) + +- **R**eference — What sources, data, or authorities are cited? +- **I**nsight — What unique perspectives or non-obvious points are made? +- **S**ummary — What are the essential takeaways? +- **E**valuation — What are the strengths and weaknesses of the arguments? + +### Prompt Template for Summary Generation + +When generating the summary from the transcript, use this structure: + +``` +You are summarizing a YouTube video transcript. Follow these rules strictly: + +1. TITLE & METADATA + - Video title (if known) + - Estimated duration from timestamps + - Primary topic/category + +2. EXECUTIVE SUMMARY (2-3 sentences) + - The single most important takeaway + - Who should watch this and why + +3. KEY POINTS (bulleted, with timestamps) + - [MM:SS] Point description + - Maximum 10 key points + - Each point should be self-contained and actionable + +4. DETAILED NOTES (organized by topic/section) + - Group related content under headers + - Include specific examples, numbers, quotes + - Preserve technical accuracy + +5. STAR ANALYSIS + - Situation: ... + - Task: ... + - Action: ... + - Result: ... + +6. ACTIONABLE TAKEAWAYS + - What the viewer should do after watching + - Resources mentioned in the video +``` + +--- + +## Workflows + +### Workflow 1: Quick Summary + +User says: "Summarize this video: https://youtube.com/watch?v=..." + +1. Extract video ID from URL +2. Fetch English transcript (fall back to auto-generated) +3. Generate executive summary + key points with timestamps +4. Present in clean markdown format + +### Workflow 2: Deep Dive Notes + +User says: "I need detailed study notes from this lecture" + +1. Extract video ID +2. Fetch transcript in preferred language +3. Generate full STAR + R-I-S-E analysis +4. Include all timestamps, quotes, and specific data points +5. Add a "Review Questions" section at the end + +### Workflow 3: Multi-Language Summary + +User says: "Summarize this Chinese/Japanese/Korean video in English" + +1. Extract video ID +2. List available transcript languages +3. Fetch best available transcript +4. Translate content if needed (use transcript API's built-in translation) +5. Generate summary in the user's preferred language + +### Workflow 4: Batch Processing + +User provides multiple URLs: + +1. Extract all video IDs +2. Fetch transcripts sequentially (respect rate limits) +3. Generate individual summaries +4. Create a comparison table if videos are related +5. Highlight common themes and unique points + +### Workflow 5: Timestamp Navigation + +User says: "Find where they talk about X in this video" + +1. Fetch full transcript +2. Search for relevant keywords/concepts +3. Return matching segments with precise timestamps +4. Format as clickable timestamp links: `[MM:SS](https://youtu.be/ID?t=SECONDS)` + +--- + +## Output Format + +### Standard Summary Output + +```markdown +# 📺 Video Summary: [Title] + +**Duration**: ~XX minutes | **Language**: English | **Category**: Technology + +## Executive Summary +[2-3 sentence overview] + +## Key Points +- **[0:00]** Introduction and context setting +- **[2:15]** First major point with supporting evidence +- **[8:30]** Key technical concept explained +- **[15:00]** Practical demonstration +- **[22:45]** Conclusion and call to action + +## Detailed Notes + +### Section 1: [Topic] (0:00 - 5:30) +[Detailed notes with specific information] + +### Section 2: [Topic] (5:30 - 12:00) +[Detailed notes with specific information] + +## STAR Analysis +- **Situation**: [Context] +- **Task**: [Problem/Question] +- **Action**: [Methods/Steps] +- **Result**: [Outcomes/Conclusions] + +## Actionable Takeaways +1. [First action item] +2. [Second action item] +3. [Third action item] + +## Resources Mentioned +- [Resource 1](url) +- [Resource 2](url) +``` + +--- + +## Common Pitfalls + +### 1. Transcript Unavailable + +**Problem**: Some videos have no transcript (auto-generated or manual). + +**Solutions**: +- Check if the video is a music video, live stream, or very short clip — these often lack transcripts +- Try different language codes: `['en', 'en-US', 'en-GB']` +- If auto-generated is disabled by the uploader, there's no workaround via this API + +**Error handling**: +```python +try: + transcript = fetch_transcript(video_id) +except RuntimeError as e: + if "disabled" in str(e).lower(): + print("Subtitles are disabled for this video by the uploader.") + elif "no transcript" in str(e).lower(): + print("No transcript available. Try a different video.") + else: + print(f"Unexpected error: {e}") +``` + +### 2. Age-Restricted or Private Videos + +**Problem**: Age-restricted videos require authentication; private videos are inaccessible. + +**Solution**: Inform the user that these videos cannot be processed without authentication cookies. The `youtube-transcript-api` does not support cookie-based auth natively. + +### 3. Rate Limiting + +**Problem**: Fetching many transcripts in quick succession may trigger rate limits. + +**Solutions**: +- Add a 1-2 second delay between requests when batch processing +- Cache transcripts locally to avoid re-fetching +- Handle HTTP 429 errors with exponential backoff + +```python +import time + +def fetch_with_retry(video_id, max_retries=3): + for attempt in range(max_retries): + try: + return fetch_transcript(video_id) + except Exception as e: + if '429' in str(e) and attempt < max_retries - 1: + wait = 2 ** (attempt + 1) + time.sleep(wait) + continue + raise +``` + +### 4. Transcript Quality Issues + +**Problem**: Auto-generated transcripts may contain errors, especially for technical terms, proper nouns, or non-English content. + +**Solutions**: +- Prefer manually created transcripts when available +- Flag to the user that auto-generated transcripts may have inaccuracies +- Use context clues to correct obvious errors in the summary + +### 5. Very Long Videos + +**Problem**: Videos over 2 hours may produce extremely long transcripts that exceed context limits. + +**Solutions**: +- Chunk the transcript into segments (e.g., 15-minute blocks) +- Summarize each chunk independently, then create an overall summary +- Let the user specify a time range to focus on + +```python +def chunk_transcript(transcript, chunk_minutes=15): + """Split transcript into time-based chunks.""" + chunks = [] + current_chunk = [] + chunk_end = chunk_minutes * 60 + + for segment in transcript: + if segment['start'] >= chunk_end and current_chunk: + chunks.append(current_chunk) + current_chunk = [] + chunk_end += chunk_minutes * 60 + current_chunk.append(segment) + + if current_chunk: + chunks.append(current_chunk) + + return chunks +``` + +### 6. Invalid or Expired URLs + +**Problem**: Shortened URLs, expired links, or non-YouTube URLs. + +**Solution**: Validate the extracted video ID format (11 characters, `[A-Za-z0-9_-]`) before making API calls. Return a clear error message for invalid inputs. + +--- + +## Advanced: Combining with Video Metadata + +For richer summaries, consider fetching video metadata (title, channel, description) using the YouTube Data API v3 or by parsing the video page. This adds context but requires either an API key or HTML parsing. + +The transcript-only approach used here is intentionally lightweight — no API key needed, no OAuth, minimal dependencies. + +--- + +## Language Support + +The `youtube-transcript-api` supports all languages that YouTube provides transcripts for. Common language codes: + +| Language | Code | Auto-generated | +|---|---|---| +| English | `en` | Yes | +| Chinese (Simplified) | `zh-Hans` | Yes | +| Chinese (Traditional) | `zh-Hant` | Yes | +| Japanese | `ja` | Yes | +| Korean | `ko` | Yes | +| Spanish | `es` | Yes | +| French | `fr` | Yes | +| German | `de` | Yes | +| Portuguese | `pt` | Yes | +| Russian | `ru` | Yes | + +To get all available languages for a video: + +```python +transcript_list = YouTubeTranscriptApi.list_transcripts(video_id) +for t in transcript_list: + print(f"{t.language} ({t.language_code}) - {'manual' if not t.is_generated else 'auto'}") +``` diff --git a/account/admin/skills/yuque-skills/.openakita-i18n.json b/account/admin/skills/yuque-skills/.openakita-i18n.json new file mode 100644 index 0000000..2feecf7 --- /dev/null +++ b/account/admin/skills/yuque-skills/.openakita-i18n.json @@ -0,0 +1,6 @@ +{ + "zh": { + "name": "语雀知识管理", + "description": "通过语雀 API 管理知识库、文档和团队协作,支持搜索、周报生成、文档 CRUD 和内容同步。" + } +} diff --git a/account/admin/skills/yuque-skills/SKILL.md b/account/admin/skills/yuque-skills/SKILL.md new file mode 100644 index 0000000..eee2898 --- /dev/null +++ b/account/admin/skills/yuque-skills/SKILL.md @@ -0,0 +1,546 @@ +--- +name: openakita/skills@yuque-skills +description: Manage Yuque (语雀) knowledge bases, documents, and team collaboration through API integration. Supports personal search, weekly reports, knowledge base management, document CRUD, and group collaboration workflows. Based on yuque/yuque-skills. +license: MIT +metadata: + author: openakita + version: "1.0.0" +--- + +# Yuque Skills — 语雀知识管理 + +## When to Use + +- 用户需要搜索语雀中的文档和知识 +- 需要创建、编辑、发布语雀文档 +- 需要生成周报/月报并发布到语雀 +- 需要管理知识库结构(目录、分类) +- 需要在团队知识库中进行协作 +- 需要从语雀导出文档或同步内容 +- 需要统计知识库的使用数据 + +--- + +## Prerequisites + +### 必需配置 + +| 配置项 | 说明 | +|--------|------| +| `YUQUE_TOKEN` | 语雀 API Token | +| `YUQUE_HOST` | 语雀 API 地址(默认 `https://www.yuque.com/api/v2`) | + +**获取 Token:** + +1. 登录语雀 → 点击头像 → 设置 → Token +2. 或访问:https://www.yuque.com/settings/tokens +3. 创建新 Token,勾选所需权限 + +在 `.env` 中配置: + +``` +YUQUE_TOKEN=your_yuque_token_here +YUQUE_HOST=https://www.yuque.com/api/v2 +``` + +> 企业版语雀的 Host 格式为 `https://your-company.yuque.com/api/v2` + +### 必需依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `httpx` | HTTP API 调用 | `pip install httpx` | + +### 可选依赖 + +| 依赖 | 用途 | 安装方式 | +|------|------|---------| +| `markdownify` | HTML → Markdown 转换 | `pip install markdownify` | +| `beautifulsoup4` | HTML 解析 | `pip install beautifulsoup4` | + +### 验证配置 + +```bash +curl -s -H "X-Auth-Token: $YUQUE_TOKEN" "https://www.yuque.com/api/v2/user" | python -m json.tool +``` + +--- + +## Instructions + +### 语雀核心概念 + +| 概念 | 英文 | 说明 | +|------|------|------| +| 用户 | User | 个人账号 | +| 团队 | Group | 组织/团队空间 | +| 知识库 | Book/Repo | 文档集合,类似文件夹 | +| 文档 | Doc | 具体的内容页面 | +| 目录 | TOC | 知识库内的文档组织结构 | +| 协作者 | Collaborator | 知识库的共同维护者 | + +### API 基础调用 + +所有 API 请求需携带 Token: + +```python +import httpx + +YUQUE_HOST = os.environ.get("YUQUE_HOST", "https://www.yuque.com/api/v2") +YUQUE_TOKEN = os.environ["YUQUE_TOKEN"] + +headers = { + "X-Auth-Token": YUQUE_TOKEN, + "Content-Type": "application/json", + "User-Agent": "OpenAkita-Agent/1.0" +} + +async def yuque_api(method, path, data=None): + async with httpx.AsyncClient() as client: + url = f"{YUQUE_HOST}{path}" + response = await client.request(method, url, headers=headers, json=data) + response.raise_for_status() + return response.json()["data"] +``` + +### 权限说明 + +| 权限 | 可执行操作 | +|------|-----------| +| 只读 | 搜索、查看文档、导出 | +| 读写 | 创建、编辑、删除文档 | +| 管理 | 知识库设置、成员管理 | + +--- + +## Workflows + +### Workflow 1: 个人文档搜索 + +**步骤 1 — 获取用户信息** + +```python +user = await yuque_api("GET", "/user") +user_login = user["login"] +print(f"当前用户: {user['name']} ({user_login})") +``` + +**步骤 2 — 搜索文档** + +```python +async def search_docs(query, scope="user"): + """搜索语雀文档""" + params = { + "q": query, + "type": "doc", + "scope": scope, + } + result = await yuque_api("GET", f"/search?q={query}&type=doc") + return result +``` + +**步骤 3 — 获取文档内容** + +```python +async def get_doc(repo_slug, doc_slug): + """获取文档详细内容""" + doc = await yuque_api("GET", f"/repos/{repo_slug}/docs/{doc_slug}") + return { + "title": doc["title"], + "body": doc["body"], # Markdown 格式 + "body_html": doc["body_html"], # HTML 格式 + "word_count": doc["word_count"], + "updated_at": doc["updated_at"], + } +``` + +**步骤 4 — 返回搜索结果摘要** + +--- + +### Workflow 2: 周报/月报生成 + +**步骤 1 — 收集周报内容** + +向用户询问或从其他来源汇总: + +| 模块 | 内容 | +|------|------| +| 本周完成 | 已完成的工作项列表 | +| 进行中 | 正在推进的工作 | +| 下周计划 | 下周的工作安排 | +| 风险与阻塞 | 需要协助的问题 | +| 数据指标 | 关键 KPI 变化 | + +**步骤 2 — 生成 Markdown 内容** + +```python +def generate_weekly_report(data): + """生成周报 Markdown""" + report = f"""# 周报 | {data['date_range']} + +## ✅ 本周完成 + +{format_task_list(data['completed'])} + +## 🔄 进行中 + +{format_task_list(data['in_progress'])} + +## 📋 下周计划 + +{format_task_list(data['next_week'])} + +## ⚠️ 风险与阻塞 + +{format_risk_list(data['risks'])} + +## 📊 关键指标 + +{format_metrics_table(data['metrics'])} +""" + return report +``` + +**步骤 3 — 发布到语雀** + +```python +async def publish_report(repo_slug, title, content): + """发布周报到指定知识库""" + doc_data = { + "title": title, + "slug": generate_slug(title), + "body": content, + "format": "markdown", + "status": 1, # 0=草稿, 1=发布 + } + result = await yuque_api("POST", f"/repos/{repo_slug}/docs", data=doc_data) + return result +``` + +**步骤 4 — 返回文档链接** + +--- + +### Workflow 3: 知识库管理 + +**列出所有知识库** + +```python +async def list_repos(user_login=None, group_login=None): + """列出知识库""" + if group_login: + repos = await yuque_api("GET", f"/groups/{group_login}/repos") + else: + repos = await yuque_api("GET", f"/users/{user_login}/repos") + + return [{ + "id": r["id"], + "name": r["name"], + "slug": r["slug"], + "description": r["description"], + "docs_count": r["items_count"], + "namespace": r["namespace"], + "public": r["public"], + "updated_at": r["updated_at"], + } for r in repos] +``` + +**获取知识库目录** + +```python +async def get_toc(repo_namespace): + """获取知识库的目录结构""" + toc = await yuque_api("GET", f"/repos/{repo_namespace}/toc") + return toc +``` + +**创建知识库** + +```python +async def create_repo(user_or_group_login, name, description="", public=0): + """创建新知识库""" + data = { + "name": name, + "slug": slugify(name), + "description": description, + "public": public, # 0=私有, 1=公开 + "type": "Book", + } + result = await yuque_api("POST", f"/users/{user_or_group_login}/repos", data=data) + return result +``` + +--- + +### Workflow 4: 文档 CRUD 操作 + +**创建文档** + +```python +async def create_doc(repo_namespace, title, body, format="markdown"): + data = { + "title": title, + "slug": generate_slug(title), + "body": body, + "format": format, + } + return await yuque_api("POST", f"/repos/{repo_namespace}/docs", data=data) +``` + +**更新文档** + +```python +async def update_doc(repo_namespace, doc_id, title=None, body=None): + data = {} + if title: + data["title"] = title + if body: + data["body"] = body + return await yuque_api("PUT", f"/repos/{repo_namespace}/docs/{doc_id}", data=data) +``` + +**删除文档** + +```python +async def delete_doc(repo_namespace, doc_id): + return await yuque_api("DELETE", f"/repos/{repo_namespace}/docs/{doc_id}") +``` + +**导出文档** + +```python +async def export_doc(repo_namespace, doc_slug, format="markdown"): + """导出文档为指定格式""" + doc = await get_doc(repo_namespace, doc_slug) + if format == "markdown": + return doc["body"] + elif format == "html": + return doc["body_html"] + elif format == "text": + from bs4 import BeautifulSoup + return BeautifulSoup(doc["body_html"], "html.parser").get_text() +``` + +--- + +### Workflow 5: 团队协作 + +**列出团队** + +```python +async def list_groups(): + """列出用户加入的所有团队""" + groups = await yuque_api("GET", "/users/groups") + return [{ + "id": g["id"], + "name": g["name"], + "login": g["login"], + "description": g["description"], + "members_count": g["members_count"], + } for g in groups] +``` + +**团队知识库报告** + +```python +async def generate_team_report(group_login): + """生成团队知识库使用报告""" + repos = await list_repos(group_login=group_login) + + report = { + "total_repos": len(repos), + "total_docs": sum(r["docs_count"] for r in repos), + "repos_detail": [], + } + + for repo in repos: + docs = await yuque_api("GET", f"/repos/{repo['namespace']}/docs") + recent_docs = sorted(docs, key=lambda d: d["updated_at"], reverse=True)[:5] + report["repos_detail"].append({ + "name": repo["name"], + "doc_count": repo["docs_count"], + "recent_updates": [d["title"] for d in recent_docs], + }) + + return report +``` + +**知识库协作者管理** + +```python +async def add_collaborator(repo_namespace, user_login, role="writer"): + """添加知识库协作者""" + data = { + "login": user_login, + "role": role, # reader, writer, admin + } + return await yuque_api("POST", f"/repos/{repo_namespace}/collaborators", data=data) +``` + +--- + +### Workflow 6: 知识库内容同步 + +将外部内容同步到语雀,或从语雀同步到本地: + +**从 Markdown 文件同步到语雀** + +```python +async def sync_markdown_to_yuque(md_dir, repo_namespace): + """将本地 Markdown 文件目录同步到语雀知识库""" + import glob + + md_files = glob.glob(f"{md_dir}/**/*.md", recursive=True) + + for md_file in md_files: + with open(md_file, "r", encoding="utf-8") as f: + content = f.read() + + title = os.path.splitext(os.path.basename(md_file))[0] + + existing = await search_doc_by_title(repo_namespace, title) + if existing: + await update_doc(repo_namespace, existing["id"], body=content) + print(f"更新: {title}") + else: + await create_doc(repo_namespace, title, content) + print(f"创建: {title}") +``` + +**从语雀导出到本地** + +```python +async def export_repo_to_local(repo_namespace, output_dir): + """将语雀知识库导出为本地 Markdown 文件""" + docs = await yuque_api("GET", f"/repos/{repo_namespace}/docs") + + os.makedirs(output_dir, exist_ok=True) + + for doc_info in docs: + doc = await get_doc(repo_namespace, doc_info["slug"]) + file_path = os.path.join(output_dir, f"{doc_info['slug']}.md") + with open(file_path, "w", encoding="utf-8") as f: + f.write(f"# {doc['title']}\n\n{doc['body']}") + print(f"导出: {doc['title']} -> {file_path}") +``` + +--- + +## Output Format + +### 搜索结果 + +``` +🔍 搜索 "项目规范" 共找到 5 条结果: + +1. 📄 代码规范 v2.0 + - 知识库: 工程团队/开发规范 + - 更新时间: 2025-02-28 + - 链接: https://www.yuque.com/team/repo/doc-slug + +2. 📄 项目管理规范 + - 知识库: PMO/流程文档 + - 更新时间: 2025-02-25 + - 链接: https://www.yuque.com/team/repo/doc-slug2 + +... +``` + +### 周报输出 + +生成后返回发布链接和摘要。 + +### 知识库统计 + +``` +📊 团队知识库统计 +- 总知识库数: 12 +- 总文档数: 456 +- 本月新增: 28 篇 +- 最活跃知识库: "产品设计" (本月 12 篇更新) +- 最近更新: + 1. API 接口文档 v3 (2 小时前) + 2. Q1 OKR 复盘 (昨天) + 3. 新员工入职手册 (3 天前) +``` + +--- + +## Common Pitfalls + +### 1. Token 权限不足 + +**症状**:API 返回 401 或 403 +**解决**: +- 确认 Token 有读写权限 +- 企业版语雀可能需要管理员授权 +- 检查 Token 是否过期 + +### 2. namespace 格式错误 + +语雀的 namespace 格式为 `{user_or_group_login}/{repo_slug}`,例如 `myteam/dev-docs`。 + +**错误**:使用 repo 名称代替 slug +**正确**:使用 URL 中的 slug + +### 3. Markdown 与 HTML 格式混淆 + +语雀文档有两种内容格式: +- `body`:Markdown 格式(创建时使用 `format: "markdown"`) +- `body_html`:HTML 格式 + +创建文档时需明确指定 `format` 参数。 + +### 4. API 频率限制 + +语雀 API 有请求频率限制: +- 个人版:约 100 次/分钟 +- 企业版:通常更高 + +**解决**:批量操作时添加延迟: + +```python +import asyncio +for doc in docs: + await process_doc(doc) + await asyncio.sleep(0.5) +``` + +### 5. 文档 slug 冲突 + +同一知识库中 slug 必须唯一。创建文档前先检查是否已存在: + +```python +async def safe_create_doc(repo_namespace, title, body): + slug = generate_slug(title) + existing = await find_doc_by_slug(repo_namespace, slug) + if existing: + slug = f"{slug}-{int(time.time())}" + return await create_doc(repo_namespace, title, body, slug=slug) +``` + +### 6. 企业版与个人版 API 差异 + +企业版语雀的部分 API 路径和参数可能有差异: +- Host 不同(`your-company.yuque.com`) +- 部分接口需要额外权限 +- 团队管理接口更丰富 + +### 7. 大文档性能问题 + +超过 5 万字的文档在创建/更新时可能超时。建议: +- 拆分为多篇文档 +- 使用分页上传 +- 图片先上传到 CDN 再引用 + +--- + +## EXTEND.md 扩展 + +用户可在技能同目录下创建 `EXTEND.md` 添加: +- 默认知识库 namespace +- 团队的语雀 Host 地址 +- 周报/月报模板定制 +- 常用知识库列表和别名 +- 自定义文档模板 diff --git a/plan/agent-implementation-plan.md b/plan/agent-implementation-plan.md new file mode 100644 index 0000000..9edc8c6 --- /dev/null +++ b/plan/agent-implementation-plan.md @@ -0,0 +1,655 @@ +# 智能体系统实现计划 + +## 项目概述 + +设计并实现一个支持单智能体独立工作 + 多智能体协作的混合型智能体系统,具备长短时记忆、多种技能调用能力。 + +## 技术架构 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 用户请求入口 │ +└─────────────────────────────┬───────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ API Gateway (Go) │ +│ /api/v1/agents/:id/chat │ +└─────────────────────────────┬───────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────────┐ +│ Agent Engine (Python) │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Agent Core │ │ Supervisor │ │ Memory │ │ +│ │ (单智能体) │ │ (多智能体) │ │ (长短时) │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ +│ │ │ │ │ +│ └────────┬────────┴──────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ Skill Router (技能路由器) │ │ +│ └──────────────────────────┬───────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ Skill Executor (执行器) │ │ +│ └──────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## 1. 数据库设计 + +### 1.1 新增表结构 + +```sql +-- 智能体配置表 (agents) +CREATE TABLE agents ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + role_description TEXT, + model_provider VARCHAR(50), + model_name VARCHAR(100), + status VARCHAR(20) DEFAULT 'active', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +-- 技能绑定表 +CREATE TABLE agent_skills ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + agent_id BIGINT NOT NULL, + skill_id BIGINT NOT NULL, + skill_config JSON, + FOREIGN KEY (agent_id) REFERENCES agents(id), + FOREIGN KEY (skill_id) REFERENCES skills(id) +); + +-- 知识库绑定表 +CREATE TABLE agent_knowledge_bases ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + agent_id BIGINT NOT NULL, + knowledge_base_id BIGINT NOT NULL, + FOREIGN KEY (agent_id) REFERENCES agents(id), + FOREIGN KEY (knowledge_base_id) REFERENCES knowledge_bases(id) +); + +-- 长期记忆表 +CREATE TABLE agent_memories ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + agent_id BIGINT NOT NULL, + user_id BIGINT, + content TEXT NOT NULL, + embedding VECTOR(1536), + memory_type VARCHAR(20), + importance INT DEFAULT 5, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (agent_id) REFERENCES agents(id) +); + +-- 会话记忆 (Redis) +-- Key: session:{agent_id}:{user_id}:{session_id} +-- Value: JSON {"messages": [...], "summary": "..."} + +-- 任务记录表 +CREATE TABLE agent_tasks ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + agent_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + user_input TEXT NOT NULL, + agent_response TEXT, + status VARCHAR(20), + tokens_used INT DEFAULT 0, + duration_ms INT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + completed_at DATETIME, + FOREIGN KEY (agent_id) REFERENCES agents(id) +); + +-- 多智能体协作配置表 +CREATE TABLE agent_teams ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + supervisor_agent_id BIGINT NOT NULL, + member_agent_id BIGINT NOT NULL, + dispatch_strategy VARCHAR(20) DEFAULT 'parallel', + FOREIGN KEY (supervisor_agent_id) REFERENCES agents(id), + FOREIGN KEY (member_agent_id) REFERENCES agents(id) +); +``` + +## 2. 后端实现 (Python Agent Engine) + +### 2.1 项目结构 + +``` +agent/ +├── app/ +│ ├── agent/ +│ │ ├── __init__.py +│ │ ├── core/ +│ │ │ ├── __init__.py +│ │ │ ├── agent.py # AgentCore 单智能体核心 +│ │ │ ├── supervisor.py # Supervisor 多智能体调度 +│ │ │ └── config.py # Agent 配置模型 +│ │ ├── skills/ +│ │ │ ├── __init__.py +│ │ │ ├── router.py # 技能路由器 +│ │ │ ├── executor.py # 技能执行器 +│ │ │ └── registry.py # 技能注册表 +│ │ ├── memory/ +│ │ │ ├── __init__.py +│ │ │ ├── manager.py # 记忆管理器 +│ │ │ ├── working.py # Working Memory +│ │ │ ├── session.py # Session Memory (Redis) +│ │ │ └── persistent.py # Persistent Memory (向量库) +│ │ ├── llm/ +│ │ │ ├── __init__.py +│ │ │ ├── base.py # LLM 抽象基类 +│ │ │ ├── openai.py # OpenAI 实现 +│ │ │ └── anthropic.py # Anthropic 实现 +│ │ └── tools/ +│ │ ├── __init__.py +│ │ └── registry.py # 工具注册表 (复用现有) +│ ├── api/ +│ │ ├── __init__.py +│ │ └── routes/ +│ │ ├── __init__.py +│ │ └── agent.py # Agent API 路由 +│ └── main.py +├── requirements.txt +└── config.yaml +``` + +### 2.2 核心代码设计 + +#### AgentCore (单智能体核心) + +```python +# agent/app/agent/core/agent.py +from typing import Optional, List +from pydantic import BaseModel +from app.agent.memory.manager import MemoryManager +from app.agent.skills.router import SkillRouter +from app.agent.skills.executor import SkillExecutor +from app.agent.llm.base import LLMBase + +class AgentConfig(BaseModel): + id: int + name: str + role_description: str + model_provider: str + model_name: str + skills: List[int] # 技能 ID 列表 + knowledge_base_ids: List[int] = [] + +class AgentResponse(BaseModel): + content: str + tool_calls: List[dict] = [] + tokens_used: int = 0 + duration_ms: int = 0 + +class AgentCore: + def __init__(self, config: AgentConfig, llm: LLMBase): + self.config = config + self.llm = llm + self.memory = MemoryManager(config.id) + self.skill_router = SkillRouter(config.skills) + self.skill_executor = SkillExecutor() + + async def run(self, user_input: str, user_id: int) -> AgentResponse: + start_time = time.time() + + # 1. 加载记忆 + context = await self.memory.load_context(user_input, user_id) + + # 2. 构建 Prompt + prompt = self._build_prompt(user_input, context) + + # 3. LLM 决策 + decision = await self.llm.decide(prompt) + + # 4. 执行技能(如需) + if decision.needs_skill: + skill_results = await self._execute_skills(decision.skills) + # 5. 基于结果生成回复 + final_response = await self.llm.generate(prompt, skill_results) + else: + final_response = decision.response + + # 6. 保存记忆 + await self.memory.save(user_input, final_response) + + duration_ms = int((time.time() - start_time) * 1000) + + return AgentResponse( + content=final_response, + tool_calls=decision.tool_calls, + duration_ms=duration_ms + ) + + def _build_prompt(self, user_input: str, context: dict) -> str: + system_prompt = f"""你是 {self.config.name}。 +{self.config.role_description} + +相关记忆: +{context.get('summary', '')} +""" + return f"{system_prompt}\n\n用户: {user_input}" + + async def _execute_skills(self, skill_decisions: List[dict]) -> List[dict]: + results = [] + for decision in skill_decisions: + result = await self.skill_executor.execute( + skill_id=decision['skill_id'], + params=decision['params'] + ) + results.append(result) + return results +``` + +#### Supervisor (多智能体调度) + +```python +# agent/app/agent/core/supervisor.py +from typing import List +from app.agent.core.agent import AgentCore, AgentConfig + +class Supervisor: + def __init__(self, supervisor_agent: AgentCore, members: List[AgentCore], strategy: str = "parallel"): + self.supervisor = supervisor_agent + self.members = members + self.strategy = strategy + + async def run(self, task: str, user_id: int) -> dict: + # 1. 任务分解 (调用 Supervisor 的 LLM) + subtasks = await self._decompose_task(task) + + # 2. 分配任务 + if self.strategy == "parallel": + results = await self._dispatch_parallel(subtasks, user_id) + else: + results = await self._dispatch_sequential(subtasks, user_id) + + # 3. 汇总结果 + final_result = await self._aggregate(results) + + return { + "main_response": final_result, + "subtask_results": results + } + + async def _decompose_task(self, task: str) -> List[dict]: + # 调用 LLM 分解任务 + prompt = f"""分解以下任务为子任务,返回 JSON 数组: +任务: {task} + +格式: [{"task": "子任务描述", "agent_type": "适合的智能体类型"}]""" + # ... 实现 + return subtasks + + async def _dispatch_parallel(self, subtasks: List[dict], user_id: int) -> List[dict]: + tasks = [] + for subtask, member in zip(subtasks, self.members): + tasks.append(member.run(subtask['task'], user_id)) + return await asyncio.gather(*tasks) + + async def _dispatch_sequential(self, subtasks: List[dict], user_id: int) -> List[dict]: + results = [] + context = "" + for subtask in subtasks: + # 传递前一个结果作为上下文 + enhanced_task = f"{context}\n\n当前任务: {subtask['task']}" + result = await self.members[self.members.index(subtask['agent'])].run(enhanced_task, user_id) + results.append(result) + context += f"\n{result.content}" + return results + + async def _aggregate(self, results: List[dict]) -> str: + # 汇总所有子任务结果 + prompt = "汇总以下结果:\n" + "\n---\n".join([r['content'] for r in results]) + return await self.supervisor.llm.generate(prompt, []) +``` + +#### Memory Manager (记忆管理) + +```python +# agent/app/agent/memory/manager.py +from app.agent.memory.working import WorkingMemory +from app.agent.memory.session import SessionMemory +from app.agent.memory.persistent import PersistentMemory + +class MemoryManager: + def __init__(self, agent_id: int): + self.agent_id = agent_id + self.working = WorkingMemory() + self.session = SessionMemory(agent_id) + self.persistent = PersistentMemory(agent_id) + + async def load_context(self, query: str, user_id: int, session_id: str) -> dict: + # 1. Working Memory (内存,最快) + working_context = self.working.get() + + # 2. Session Memory (Redis) + session_context = await self.session.get_summary(user_id, session_id) + + # 3. Persistent Memory (向量库) - 按需检索 + persistent_context = await self.persistent.search(query, user_id, top_k=3) + + return { + 'working': working_context, + 'session': session_context, + 'persistent': persistent_context, + 'summary': self._build_summary(session_context, persistent_context) + } + + async def save(self, user_input: str, response: str, user_id: int, session_id: str): + # 1. 写入 Working + self.working.add(user_input, response) + + # 2. 写入 Session (定期摘要) + await self.session.add(user_input, response, user_id, session_id) + + # 3. 提取关键信息写入 Persistent (定期) + if self._should_persist(): + await self._extract_and_persist(user_input, response, user_id) + + def _should_persist(self) -> bool: + # 每 N 条对话或达到阈值时持久化 + return self.working.size() >= 5 + + async def _extract_and_persist(self, user_input: str, response: str, user_id: int): + # 提取关键信息(可以用 LLM 或规则) + key_points = self._extract_key_points(user_input, response) + for point in key_points: + await self.persistent.add(point, user_id, memory_type="experience") +``` + +```python +# agent/app/agent/memory/working.py +class WorkingMemory: + """当前任务上下文,内存级存储""" + + def __init__(self): + self.current_task = None + self.recent_messages = [] + self.max_size = 10 + + def get(self) -> dict: + return { + 'current_task': self.current_task, + 'recent_messages': self.recent_messages[-self.max_size:] + } + + def add(self, user_input: str, response: str): + self.recent_messages.append({ + 'role': 'user', + 'content': user_input + }) + self.recent_messages.append({ + 'role': 'assistant', + 'content': response + }) + # 保持固定大小 + if len(self.recent_messages) > self.max_size * 2: + self.recent_messages = self.recent_messages[-self.max_size:] + + def size(self) -> int: + return len(self.recent_messages) // 2 +``` + +```python +# agent/app/agent/memory/session.py +import redis.asyncio as redis +import json + +class SessionMemory: + """会话级记忆,Redis 存储""" + + def __init__(self, agent_id: int, redis_client: redis.Redis): + self.agent_id = agent_id + self.redis = redis_client + self.ttl = 3600 * 24 # 24 小时 + + def _key(self, user_id: int, session_id: str) -> str: + return f"agent:memory:session:{self.agent_id}:{user_id}:{session_id}" + + async def add(self, user_input: str, response: str, user_id: int, session_id: str): + key = self._key(user_id, session_id) + + # 获取现有数据 + data = await self.redis.get(key) + messages = json.loads(data) if data else {"messages": [], "summary": ""} + + # 添加新消息 + messages["messages"].append({"role": "user", "content": user_input}) + messages["messages"].append({"role": "assistant", "content": response}) + + # 定期生成摘要 + if len(messages["messages"]) >= 10: + messages["summary"] = await self._generate_summary(messages["messages"]) + + await self.redis.setex(key, self.ttl, json.dumps(messages)) + + async def get_summary(self, user_id: int, session_id: str) -> str: + key = self._key(user_id, session_id) + data = await self.redis.get(key) + if data: + messages = json.loads(data) + return messages.get("summary", "") + return "" + + async def _generate_summary(self, messages: List[dict]) -> str: + # 使用 LLM 生成摘要 + # ... + return summary +``` + +```python +# agent/app/agent/memory/persistent.py +from typing import List + +class PersistentMemory: + """长期记忆,向量存储""" + + def __init__(self, agent_id: int): + self.agent_id = agent_id + self.vector_store = None # 初始化向量库客户端 + + async def add(self, content: str, user_id: int, memory_type: str = "experience"): + # 生成向量 + embedding = await self._get_embedding(content) + + # 存储到数据库 + await db.agent_memories.create( + agent_id=self.agent_id, + user_id=user_id, + content=content, + embedding=embedding, + memory_type=memory_type + ) + + async def search(self, query: str, user_id: int, top_k: int = 3) -> List[str]: + # 生成查询向量 + query_embedding = await self._get_embedding(query) + + # 向量相似度搜索 + results = await db.agent_memories.search( + agent_id=self.agent_id, + user_id=user_id, + embedding=query_embedding, + top_k=top_k + ) + + return [r.content for r in results] + + async def _get_embedding(self, text: str) -> List[float]: + # 调用 embedding 模型 + # ... + pass +``` + +#### Skill Router (技能路由器) + +```python +# agent/app/agent/skills/router.py +from typing import List, Dict + +class SkillRouter: + """根据 LLM 决策选择要调用的技能""" + + def __init__(self, available_skills: List[int]): + self.available_skills = available_skills + + async def route(self, llm_decision: dict) -> List[dict]: + """解析 LLM 的技能调用决策""" + if not llm_decision.get('tool_calls'): + return [] + + routes = [] + for tool_call in llm_decision['tool_calls']: + skill_id = tool_call['skill_id'] + + # 检查技能是否可用 + if skill_id not in self.available_skills: + continue + + routes.append({ + 'skill_id': skill_id, + 'params': tool_call.get('parameters', {}), + 'reason': tool_call.get('reason', '') + }) + + return routes +``` + +#### Skill Executor (技能执行器) + +```python +# agent/app/agent/skills/executor.py +import asyncio + +class SkillExecutor: + """技能执行器,支持并发/串行执行""" + + def __init__(self): + self.skill_registry = None # 技能注册表 + + async def execute(self, skill_id: int, params: dict) -> dict: + """执行单个技能""" + skill = self.skill_registry.get(skill_id) + if not skill: + return {"error": f"Skill {skill_id} not found"} + + try: + result = await skill.execute(**params) + return {"success": True, "result": result} + except Exception as e: + return {"success": False, "error": str(e)} + + async def execute_multiple(self, skills: List[dict], strategy: str = "parallel") -> List[dict]: + """批量执行技能""" + if strategy == "parallel": + tasks = [self.execute(s['skill_id'], s['params']) for s in skills] + return await asyncio.gather(*tasks, return_exceptions=True) + else: + results = [] + for s in skills: + result = await self.execute(s['skill_id'], s['params']) + results.append(result) + return results +``` + +## 3. API 接口设计 + +### 3.1 新增接口 + +| 方法 | 路径 | 描述 | +|------|------|------| +| POST | /api/v1/agents/:id/chat | 单智能体对话 | +| POST | /api/v1/agents/:id/chat/stream | 单智能体流式对话 | +| POST | /api/v1/teams/:id/chat | 多智能体群聊 | +| GET | /api/v1/agents/:id/memories | 获取记忆 | +| DELETE | /api/v1/agents/:id/memories/:memory_id | 删除记忆 | +| GET | /api/v1/agents/:id/history | 获取对话历史 | + +### 3.2 接口请求/响应示例 + +```json +// POST /api/v1/agents/1/chat +// Request +{ + "user_id": 123, + "message": "帮我分析销售数据", + "session_id": "optional-session-id" +} + +// Response +{ + "agent_id": 1, + "response": "根据分析,今天销售额为...", + "tool_calls": [ + {"skill": "query_database", "params": {"sql": "SELECT ..."}} + ], + "tokens_used": 1500, + "duration_ms": 2000 +} +``` + +## 4. 实现步骤 + +### Phase 1: 数据库设计与迁移 +- [ ] 创建数据库迁移脚本 +- [ ] 新增 agents, agent_skills, agent_memories, agent_teams 等表 + +### Phase 2: 后端 Agent Engine 核心 +- [ ] 实现 AgentCore 单智能体核心类 +- [ ] 实现 LLM 适配器 (OpenAI/Anthropic) +- [ ] 实现 Prompt 构建逻辑 + +### Phase 3: 记忆系统实现 +- [ ] 实现 WorkingMemory (内存) +- [ ] 实现 SessionMemory (Redis) +- [ ] 实现 PersistentMemory (向量库) +- [ ] 实现 MemoryManager 统一接口 + +### Phase 4: 技能路由与执行器 +- [ ] 实现 SkillRouter +- [ ] 实现 SkillExecutor +- [ ] 对接现有技能注册表 + +### Phase 5: 多智能体 Supervisor +- [ ] 实现 Supervisor 调度器 +- [ ] 实现任务分解逻辑 +- [ ] 实现结果聚合 + +### Phase 6: API 接口对接 +- [ ] 新增 Agent API 路由 +- [ ] 实现 /chat, /chat/stream 等接口 +- [ ] 对接 Go API Gateway + +### Phase 7: 前端页面集成 +- [ ] 智能体详情页增加对话功能 +- [ ] 记忆管理页面 +- [ ] 多智能体协作配置页面 + +### Phase 8: 测试与优化 +- [ ] 单元测试 +- [ ] 集成测试 +- [ ] 性能优化 + +## 5. 里程碑 + +| 里程碑 | 预计时间 | 交付物 | +|--------|----------|--------| +| M1: 基础骨架 | 1 周 | 数据库 + AgentCore 基础 | +| M2: 记忆系统 | 1 周 | 三层记忆实现 | +| M3: 技能调用 | 1 周 | Router + Executor | +| M4: 多智能体 | 1 周 | Supervisor 实现 | +| M5: API 对接 | 1 周 | 完整 API | +| M6: 前端集成 | 1 周 | 页面功能 | + +## 6. 风险与对策 + +| 风险 | 影响 | 对策 | +|------|------|------| +| LLM API 不稳定 | 功能不可用 | 重试机制 + 降级 | +| 向量库性能 | 检索慢 | 缓存 + 限流 | +| Token 成本超支 | 费用上涨 | 记忆压缩 + 按需加载 | +| 多智能体通信 | 延迟增加 | 超时控制 + 并行优化 | diff --git a/plan/notes.md b/plan/notes.md new file mode 100644 index 0000000..4b85dc4 --- /dev/null +++ b/plan/notes.md @@ -0,0 +1,33 @@ +# Notes: 智能体系统设计研究 + +## 设计决策汇总 + +### 1. 架构选择 +- **方案**: 自研 Agent Core(方案 B) +- **理由**: 完全可控,易于扩展,支持多智能体调度 + +### 2. 工作模式 +- **独立模式**: 单个智能体独立处理任务 +- **协作模式**: Supervisor 调度多个子智能体 + +### 3. 记忆系统设计 +- Working Memory: 当前任务上下文(内存变量) +- Session Memory: 会话级记忆(Redis + 摘要) +- Persistent Memory: 长期记忆(向量存储) + +### 4. 性能优化策略 +- 分层检索: Working → Session → Persistent +- 记忆压缩: 摘要 + 结构化标签 +- 按需加载: LLM 决策需要什么记忆再检索 +- 缓存策略: 热门记忆放内存缓存 + +### 5. 错误处理 +- 重试机制: LLM 调用失败重试 3 次 +- 降级策略: 记忆加载失败降级到无记忆模式 +- 超时控制: 多智能体调度设置超时 + +## 技术栈确认 +- 后端: Python FastAPI (agent/) +- 记忆存储: Redis + PostgreSQL/Milvus +- LLM: OpenAI / Anthropic SDK +- 技能: 内置 + 自定义 + MCP + API diff --git a/plan/task_plan.md b/plan/task_plan.md new file mode 100644 index 0000000..0be0f8c --- /dev/null +++ b/plan/task_plan.md @@ -0,0 +1,99 @@ +# Task Plan: 智能体系统设计与实现 + +## Goal +设计和实现一个支持单智能体独立工作 + 多智能体协作的混合型智能体系统,具备长短时记忆、多种技能调用能力。 + +## Phases +- [ ] Phase 1: 数据库设计与迁移 +- [ ] Phase 2: 后端 Agent Engine 核心实现 +- [ ] Phase 3: 记忆系统实现 +- [ ] Phase 4: 技能路由与执行器实现 +- [ ] Phase 5: 多智能体 Supervisor 实现 +- [ ] Phase 6: API 接口对接 +- [ ] Phase 7: 前端页面集成 +- [ ] Phase 8: 测试与优化 + +## Key Questions +1. 如何设计长短时记忆的存储和检索? +2. 如何实现灵活的技能路由? +3. 如何支持多智能体协作? + +## Decisions Made +- 单智能体工作流: 用户输入 → 智能体思考 → 调用技能 → 返回结果 +- 多智能体模式: Supervisor 主智能体调度子智能体 +- 记忆分层: Working → Session → Persistent 三层结构 +- 技能全支持: 内置 + 自定义代码 + MCP + API + +## Errors Encountered +- (无) + +## Status +**Currently in Phase 8** - 测试与优化 + +## 完成项 +- [x] Phase 1: 数据库设计与迁移 + - 扩展 Agent 模型 (增加角色描述、模型配置、协作模式) + - 新增 AgentSkill, AgentKnowledgeBase, AgentMemory, AgentTeam, AgentTask 模型 + - 扩展 AgentRepository 添加新方法 + - 创建 SQL 迁移脚本 (server/migrations/agent_system.sql) + +- [x] Phase 2: 后端 Agent Engine 核心实现 + - AgentCore 单智能体核心类 + - Supervisor 多智能体调度器 + - LLM 适配器 (OpenAI/Anthropic) + - FastAPI 服务入口 (app/main.py) + - requirements.txt + +- [x] Phase 3: 记忆系统实现 + - Working Memory (内存) + - Session Memory (Redis/内存模拟) + - Persistent Memory (向量库/内存模拟) + - MemoryManager 统一接口 + +- [x] Phase 4: 技能路由与执行器 + - SkillRouter 技能路由器 + - SkillExecutor 技能执行器 + +- [x] Phase 5: Go API 对接 + - AgentService (调用 Python) + - AgentHandler (HTTP 接口) + - MemoryService (记忆服务) + - MemoryHandler (记忆接口) + - 路由注册 (/api/agent/chat, /api/agent/team/chat, /api/agent/:id/memories) + +- [x] Phase 7: 前端页面集成 + - agentApi.ts API 服务 + - Agents.vue 添加聊天按钮和弹窗 + +## 技术决策 +- 通信协议: HTTP REST (暂定) +- 后续可根据需要改造为 gRPC + +## 完成项 +- [x] Phase 1: 数据库设计与迁移 + - 扩展 Agent 模型 (增加角色描述、模型配置、协作模式) + - 新增 AgentSkill, AgentKnowledgeBase, AgentMemory, AgentTeam, AgentTask 模型 + - 扩展 AgentRepository 添加新方法 + - 创建 SQL 迁移脚本 (server/migrations/agent_system.sql) + +- [x] Phase 2: 后端 Agent Engine 核心实现 + - AgentCore 单智能体核心类 + - Supervisor 多智能体调度器 + - LLM 适配器 (OpenAI/Anthropic) + - FastAPI 服务入口 (app/main.py) + - requirements.txt + +- [x] Phase 3: 记忆系统实现 + - Working Memory (内存) + - Session Memory (Redis/内存模拟) + - Persistent Memory (向量库/内存模拟) + - MemoryManager 统一接口 + +- [x] Phase 4: 技能路由与执行器 + - SkillRouter 技能路由器 + - SkillExecutor 技能执行器 + +- [x] Phase 5: Go API 对接 + - AgentService (调用 Python) + - AgentHandler (HTTP 接口) + - 路由注册 (/api/agent/chat, /api/agent/team/chat)