1 Commits

Author SHA1 Message Date
qwen.ai[bot] 368426f0f4 **Title:** Implement real-time Markdown to Word conversion with advanced formatting and auto-captioning
- Added `app.py` with Flask backend for real-time Markdown to Word conversion using python-docx
- Implemented `convert_md_to_docx` function with support for headings, tables, code blocks, images, and blockquote styling
- Created `templates/index.html` with responsive UI featuring dual-panel editor/preview layout
- Added `static/script.js` for client-side functionality including live preview, toolbar buttons, and export workflow
- Enhanced `static/style.css` with modern styling for editor, preview, and settings panels
- Updated `README.md` to document features, usage, and customization options
- Added `requirements.txt` with dependencies: Flask, python-docx, markdown
- Implemented auto-captioning for images and tables with sequential numbering
- Added table pagination support with header repetition across page breaks
- Integrated configuration settings panel for customizing styles, captions, and document options
2025-12-05 01:13:54 +00:00
277 changed files with 1080 additions and 64582 deletions
-2
View File
@@ -1,2 +0,0 @@
*.bat text eol=crlf
*.cmd text eol=crlf
-41
View File
@@ -1,41 +0,0 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python application
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Install dependencies
run: |
echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
sudo apt-get install ttf-mscorefonts-installer
python -m pip install --upgrade pip
python -m venv venv
source venv/bin/activate
pip install .
- name: Run
run: |
source venv/bin/activate
python -m md2gost --syntax-highlighting examples/example.md
- uses: actions/upload-artifact@v3
with:
name: example
path: example.docx
-40
View File
@@ -1,40 +0,0 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python application
on: [push, pull_request]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Install dependencies
run: |
echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
sudo apt-get install ttf-mscorefonts-installer
sudo apt-get install fontforge
sudo apt-get install cabextract
wget https://gist.githubusercontent.com/maxwelleite/10774746/raw/ttf-vista-fonts-installer.sh -q -O - | sudo bash
python -m pip install --upgrade pip
pip install flake8 pytest
pip install .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
+39 -184
View File
@@ -1,193 +1,48 @@
# Byte-compiled / optimized / DLL files
```
# Compiled and build artifacts
*.pyc
__pycache__/
*.py[cod]
*$py.class
*.o
*.obj
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
!md2gost.spec
!md2gost.fast.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
# Dependencies
venv/
ENV/
env.bak/
venv.bak/
.venv/
node_modules/
*.egg-info/
dist/
build/
*.so
*.dylib
*.dll
# md2gost diagram PNG cache
.md2gost-cache/
md2gost/vendor/*.jar
md2gost/vendor/graphviz/
# Local ArchiMate / EA reference PDFs (licensed; not for the repo)
*.pdf
!docs/**/*.pdf
# LaTeX build artefacts
*_latex/
*.aux
# Logs and temp files
*.log
*.toc
*.out
*.fls
*.fdb_latexmk
*.xdv
_latex_tpl_tmp/
*.tmp
*.swp
*.swo
# Spyder project settings
.spyderproject
.spyproject
# Environment
.env
.env.local
.env.*
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
# Editors
.vscode/
.idea/
*.swp
*.swo
# md2gost runtime (created next to app / cwd on first run)
md2gost.schemes.json
md2gost.include-cache.json
include-cache/
.md2gost-cache/
/build-fast
build-fast/md2gost.fast/xref-md2gost.fast.html
build-fast/md2gost.fast/PYZ-00.pyz
build-fast/md2gost.fast/md2gost.pkg
build-fast/md2gost.fast/base_library.zip
# Coverage
.coverage
coverage/
htmlcov/
# OS
.DS_Store
Thumbs.db
# Testing
.pytest_cache/
.mypy_cache/
```
-1
View File
@@ -1 +0,0 @@
3.12
-30
View File
@@ -1,30 +0,0 @@
© 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.
-197
View File
@@ -1,197 +0,0 @@
---
name: word-document-processor
description: Comprehensive word document processing with full format support. Handles creation, editing, formatting preservation, tracked changes, and metadata management.
license: Proprietary. LICENSE.txt has complete terms
---
# DOCX creation, editing, and analysis
## Overview
A user may ask you to create, edit, or analyze the contents of a .docx file. A .docx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.
## Workflow Decision Tree
### Reading/Analyzing Content
Use "Text extraction" or "Raw XML access" sections below
### Creating New Document
Use "Creating a new Word document" workflow
### Editing Existing Document
- **Your own document + simple changes**
Use "Basic OOXML editing" workflow
- **Someone else's document**
Use **"Redlining workflow"** (recommended default)
- **Legal, academic, business, or government docs**
Use **"Redlining workflow"** (required)
## Reading and analyzing content
### Text extraction
If you just need to read the text contents of a document, you should convert the document to markdown using pandoc. Pandoc provides excellent support for preserving document structure and can show tracked changes:
```bash
# Convert document to markdown with tracked changes
pandoc --track-changes=all path-to-file.docx -o output.md
# Options: --track-changes=accept/reject/all
```
### Raw XML access
You need raw XML access for: comments, complex formatting, document structure, embedded media, and metadata. For any of these features, you'll need to unpack a document and read its raw XML contents.
#### Unpacking a file
`python ooxml/scripts/unpack.py <office_file> <output_directory>`
#### Key file structures
* `word/document.xml` - Main document contents
* `word/comments.xml` - Comments referenced in document.xml
* `word/media/` - Embedded images and media files
* Tracked changes use `<w:ins>` (insertions) and `<w:del>` (deletions) tags
## Creating a new Word document
When creating a new Word document from scratch, use **docx-js**, which allows you to create Word documents using JavaScript/TypeScript.
### Workflow
1. **MANDATORY - READ ENTIRE FILE**: Read [`docx-js.md`](docx-js.md) (~500 lines) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for detailed syntax, critical formatting rules, and best practices before proceeding with document creation.
2. Create a JavaScript/TypeScript file using Document, Paragraph, TextRun components (You can assume all dependencies are installed, but if not, refer to the dependencies section below)
3. Export as .docx using Packer.toBuffer()
## Editing an existing Word document
When editing an existing Word document, use the **Document library** (a Python library for OOXML manipulation). The library automatically handles infrastructure setup and provides methods for document manipulation. For complex scenarios, you can access the underlying DOM directly through the library.
### Workflow
1. **MANDATORY - READ ENTIRE FILE**: Read [`ooxml.md`](ooxml.md) (~600 lines) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for the Document library API and XML patterns for directly editing document files.
2. Unpack the document: `python ooxml/scripts/unpack.py <office_file> <output_directory>`
3. Create and run a Python script using the Document library (see "Document Library" section in ooxml.md)
4. Pack the final document: `python ooxml/scripts/pack.py <input_directory> <office_file>`
The Document library provides both high-level methods for common operations and direct DOM access for complex scenarios.
## Redlining workflow for document review
This workflow allows you to plan comprehensive tracked changes using markdown before implementing them in OOXML. **CRITICAL**: For complete tracked changes, you must implement ALL changes systematically.
**Batching Strategy**: Group related changes into batches of 3-10 changes. This makes debugging manageable while maintaining efficiency. Test each batch before moving to the next.
**Principle: Minimal, Precise Edits**
When implementing tracked changes, only mark text that actually changes. Repeating unchanged text makes edits harder to review and appears unprofessional. Break replacements into: [unchanged text] + [deletion] + [insertion] + [unchanged text]. Preserve the original run's RSID for unchanged text by extracting the `<w:r>` element from the original and reusing it.
Example - Changing "30 days" to "60 days" in a sentence:
```python
# BAD - Replaces entire sentence
'<w:del><w:r><w:delText>The term is 30 days.</w:delText></w:r></w:del><w:ins><w:r><w:t>The term is 60 days.</w:t></w:r></w:ins>'
# GOOD - Only marks what changed, preserves original <w:r> for unchanged text
'<w:r w:rsidR="00AB12CD"><w:t>The term is </w:t></w:r><w:del><w:r><w:delText>30</w:delText></w:r></w:del><w:ins><w:r><w:t>60</w:t></w:r></w:ins><w:r w:rsidR="00AB12CD"><w:t> days.</w:t></w:r>'
```
### Tracked changes workflow
1. **Get markdown representation**: Convert document to markdown with tracked changes preserved:
```bash
pandoc --track-changes=all path-to-file.docx -o current.md
```
2. **Identify and group changes**: Review the document and identify ALL changes needed, organizing them into logical batches:
**Location methods** (for finding changes in XML):
- Section/heading numbers (e.g., "Section 3.2", "Article IV")
- Paragraph identifiers if numbered
- Grep patterns with unique surrounding text
- Document structure (e.g., "first paragraph", "signature block")
- **DO NOT use markdown line numbers** - they don't map to XML structure
**Batch organization** (group 3-10 related changes per batch):
- By section: "Batch 1: Section 2 amendments", "Batch 2: Section 5 updates"
- By type: "Batch 1: Date corrections", "Batch 2: Party name changes"
- By complexity: Start with simple text replacements, then tackle complex structural changes
- Sequential: "Batch 1: Pages 1-3", "Batch 2: Pages 4-6"
3. **Read documentation and unpack**:
- **MANDATORY - READ ENTIRE FILE**: Read [`ooxml.md`](ooxml.md) (~600 lines) completely from start to finish. **NEVER set any range limits when reading this file.** Pay special attention to the "Document Library" and "Tracked Change Patterns" sections.
- **Unpack the document**: `python ooxml/scripts/unpack.py <file.docx> <dir>`
- **Note the suggested RSID**: The unpack script will suggest an RSID to use for your tracked changes. Copy this RSID for use in step 4b.
4. **Implement changes in batches**: Group changes logically (by section, by type, or by proximity) and implement them together in a single script. This approach:
- Makes debugging easier (smaller batch = easier to isolate errors)
- Allows incremental progress
- Maintains efficiency (batch size of 3-10 changes works well)
**Suggested batch groupings:**
- By document section (e.g., "Section 3 changes", "Definitions", "Termination clause")
- By change type (e.g., "Date changes", "Party name updates", "Legal term replacements")
- By proximity (e.g., "Changes on pages 1-3", "Changes in first half of document")
For each batch of related changes:
**a. Map text to XML**: Grep for text in `word/document.xml` to verify how text is split across `<w:r>` elements.
**b. Create and run script**: Use `get_node` to find nodes, implement changes, then `doc.save()`. See **"Document Library"** section in ooxml.md for patterns.
**Note**: Always grep `word/document.xml` immediately before writing a script to get current line numbers and verify text content. Line numbers change after each script run.
5. **Pack the document**: After all batches are complete, convert the unpacked directory back to .docx:
```bash
python ooxml/scripts/pack.py unpacked reviewed-document.docx
```
6. **Final verification**: Do a comprehensive check of the complete document:
- Convert final document to markdown:
```bash
pandoc --track-changes=all reviewed-document.docx -o verification.md
```
- Verify ALL changes were applied correctly:
```bash
grep "original phrase" verification.md # Should NOT find it
grep "replacement phrase" verification.md # Should find it
```
- Check that no unintended changes were introduced
## Converting Documents to Images
To visually analyze Word documents, convert them to images using a two-step process:
1. **Convert DOCX to PDF**:
```bash
soffice --headless --convert-to pdf document.docx
```
2. **Convert PDF pages to JPEG images**:
```bash
pdftoppm -jpeg -r 150 document.pdf page
```
This creates files like `page-1.jpg`, `page-2.jpg`, etc.
Options:
- `-r 150`: Sets resolution to 150 DPI (adjust for quality/size balance)
- `-jpeg`: Output JPEG format (use `-png` for PNG if preferred)
- `-f N`: First page to convert (e.g., `-f 2` starts from page 2)
- `-l N`: Last page to convert (e.g., `-l 5` stops at page 5)
- `page`: Prefix for output files
Example for specific range:
```bash
pdftoppm -jpeg -r 150 -f 2 -l 5 document.pdf page # Converts only pages 2-5
```
## Code Style Guidelines
**IMPORTANT**: When generating code for DOCX operations:
- Write concise code
- Avoid verbose variable names and redundant operations
- Avoid unnecessary print statements
## Dependencies
Required dependencies (install if not available):
- **pandoc**: `sudo apt-get install pandoc` (for text extraction)
- **docx**: `npm install -g docx` (for creating new documents)
- **LibreOffice**: `sudo apt-get install libreoffice` (for PDF conversion)
- **Poppler**: `sudo apt-get install poppler-utils` (for pdftoppm to convert PDF to images)
- **defusedxml**: `pip install defusedxml` (for secure XML parsing)
-350
View File
@@ -1,350 +0,0 @@
# DOCX Library Tutorial
Generate .docx files with JavaScript/TypeScript.
**Important: Read this entire document before starting.** Critical formatting rules and common pitfalls are covered throughout - skipping sections may result in corrupted files or rendering issues.
## Setup
Assumes docx is already installed globally
If not installed: `npm install -g docx`
```javascript
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun, Media,
Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
InternalHyperlink, TableOfContents, HeadingLevel, BorderStyle, WidthType, TabStopType,
TabStopPosition, UnderlineType, ShadingType, VerticalAlign, SymbolRun, PageNumber,
FootnoteReferenceRun, Footnote, PageBreak } = require('docx');
// Create & Save
const doc = new Document({ sections: [{ children: [/* content */] }] });
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer)); // Node.js
Packer.toBlob(doc).then(blob => { /* download logic */ }); // Browser
```
## Text & Formatting
```javascript
// IMPORTANT: Never use \n for line breaks - always use separate Paragraph elements
// ❌ WRONG: new TextRun("Line 1\nLine 2")
// ✅ CORRECT: new Paragraph({ children: [new TextRun("Line 1")] }), new Paragraph({ children: [new TextRun("Line 2")] })
// Basic text with all formatting options
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 200, after: 200 },
indent: { left: 720, right: 720 },
children: [
new TextRun({ text: "Bold", bold: true }),
new TextRun({ text: "Italic", italics: true }),
new TextRun({ text: "Underlined", underline: { type: UnderlineType.DOUBLE, color: "FF0000" } }),
new TextRun({ text: "Colored", color: "FF0000", size: 28, font: "Arial" }), // Arial default
new TextRun({ text: "Highlighted", highlight: "yellow" }),
new TextRun({ text: "Strikethrough", strike: true }),
new TextRun({ text: "x2", superScript: true }),
new TextRun({ text: "H2O", subScript: true }),
new TextRun({ text: "SMALL CAPS", smallCaps: true }),
new SymbolRun({ char: "2022", font: "Symbol" }), // Bullet •
new SymbolRun({ char: "00A9", font: "Arial" }) // Copyright © - Arial for symbols
]
})
```
## Styles & Professional Formatting
```javascript
const doc = new Document({
styles: {
default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt default
paragraphStyles: [
// Document title style - override built-in Title style
{ id: "Title", name: "Title", basedOn: "Normal",
run: { size: 56, bold: true, color: "000000", font: "Arial" },
paragraph: { spacing: { before: 240, after: 120 }, alignment: AlignmentType.CENTER } },
// IMPORTANT: Override built-in heading styles by using their exact IDs
{ id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
run: { size: 32, bold: true, color: "000000", font: "Arial" }, // 16pt
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // Required for TOC
{ id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
run: { size: 28, bold: true, color: "000000", font: "Arial" }, // 14pt
paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
// Custom styles use your own IDs
{ id: "myStyle", name: "My Style", basedOn: "Normal",
run: { size: 28, bold: true, color: "000000" },
paragraph: { spacing: { after: 120 }, alignment: AlignmentType.CENTER } }
],
characterStyles: [{ id: "myCharStyle", name: "My Char Style",
run: { color: "FF0000", bold: true, underline: { type: UnderlineType.SINGLE } } }]
},
sections: [{
properties: { page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } },
children: [
new Paragraph({ heading: HeadingLevel.TITLE, children: [new TextRun("Document Title")] }), // Uses overridden Title style
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Heading 1")] }), // Uses overridden Heading1 style
new Paragraph({ style: "myStyle", children: [new TextRun("Custom paragraph style")] }),
new Paragraph({ children: [
new TextRun("Normal with "),
new TextRun({ text: "custom char style", style: "myCharStyle" })
]})
]
}]
});
```
**Professional Font Combinations:**
- **Arial (Headers) + Arial (Body)** - Most universally supported, clean and professional
- **Times New Roman (Headers) + Arial (Body)** - Classic serif headers with modern sans-serif body
- **Georgia (Headers) + Verdana (Body)** - Optimized for screen reading, elegant contrast
**Key Styling Principles:**
- **Override built-in styles**: Use exact IDs like "Heading1", "Heading2", "Heading3" to override Word's built-in heading styles
- **HeadingLevel constants**: `HeadingLevel.HEADING_1` uses "Heading1" style, `HeadingLevel.HEADING_2` uses "Heading2" style, etc.
- **Include outlineLevel**: Set `outlineLevel: 0` for H1, `outlineLevel: 1` for H2, etc. to ensure TOC works correctly
- **Use custom styles** instead of inline formatting for consistency
- **Set a default font** using `styles.default.document.run.font` - Arial is universally supported
- **Establish visual hierarchy** with different font sizes (titles > headers > body)
- **Add proper spacing** with `before` and `after` paragraph spacing
- **Use colors sparingly**: Default to black (000000) and shades of gray for titles and headings (heading 1, heading 2, etc.)
- **Set consistent margins** (1440 = 1 inch is standard)
## Lists (ALWAYS USE PROPER LISTS - NEVER USE UNICODE BULLETS)
```javascript
// Bullets - ALWAYS use the numbering config, NOT unicode symbols
// CRITICAL: Use LevelFormat.BULLET constant, NOT the string "bullet"
const doc = new Document({
numbering: {
config: [
{ reference: "bullet-list",
levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: "first-numbered-list",
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: "second-numbered-list", // Different reference = restarts at 1
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] }
]
},
sections: [{
children: [
// Bullet list items
new Paragraph({ numbering: { reference: "bullet-list", level: 0 },
children: [new TextRun("First bullet point")] }),
new Paragraph({ numbering: { reference: "bullet-list", level: 0 },
children: [new TextRun("Second bullet point")] }),
// Numbered list items
new Paragraph({ numbering: { reference: "first-numbered-list", level: 0 },
children: [new TextRun("First numbered item")] }),
new Paragraph({ numbering: { reference: "first-numbered-list", level: 0 },
children: [new TextRun("Second numbered item")] }),
// ⚠️ CRITICAL: Different reference = INDEPENDENT list that restarts at 1
// Same reference = CONTINUES previous numbering
new Paragraph({ numbering: { reference: "second-numbered-list", level: 0 },
children: [new TextRun("Starts at 1 again (because different reference)")] })
]
}]
});
// ⚠️ CRITICAL NUMBERING RULE: Each reference creates an INDEPENDENT numbered list
// - Same reference = continues numbering (1, 2, 3... then 4, 5, 6...)
// - Different reference = restarts at 1 (1, 2, 3... then 1, 2, 3...)
// Use unique reference names for each separate numbered section!
// ⚠️ CRITICAL: NEVER use unicode bullets - they create fake lists that don't work properly
// new TextRun("• Item") // WRONG
// new SymbolRun({ char: "2022" }) // WRONG
// ✅ ALWAYS use numbering config with LevelFormat.BULLET for real Word lists
```
## Tables
```javascript
// Complete table with margins, borders, headers, and bullet points
const tableBorder = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const cellBorders = { top: tableBorder, bottom: tableBorder, left: tableBorder, right: tableBorder };
new Table({
columnWidths: [4680, 4680], // ⚠️ CRITICAL: Set column widths at table level - values in DXA (twentieths of a point)
margins: { top: 100, bottom: 100, left: 180, right: 180 }, // Set once for all cells
rows: [
new TableRow({
tableHeader: true,
children: [
new TableCell({
borders: cellBorders,
width: { size: 4680, type: WidthType.DXA }, // ALSO set width on each cell
// ⚠️ CRITICAL: Always use ShadingType.CLEAR to prevent black backgrounds in Word.
shading: { fill: "D5E8F0", type: ShadingType.CLEAR },
verticalAlign: VerticalAlign.CENTER,
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "Header", bold: true, size: 22 })]
})]
}),
new TableCell({
borders: cellBorders,
width: { size: 4680, type: WidthType.DXA }, // ALSO set width on each cell
shading: { fill: "D5E8F0", type: ShadingType.CLEAR },
children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text: "Bullet Points", bold: true, size: 22 })]
})]
})
]
}),
new TableRow({
children: [
new TableCell({
borders: cellBorders,
width: { size: 4680, type: WidthType.DXA }, // ALSO set width on each cell
children: [new Paragraph({ children: [new TextRun("Regular data")] })]
}),
new TableCell({
borders: cellBorders,
width: { size: 4680, type: WidthType.DXA }, // ALSO set width on each cell
children: [
new Paragraph({
numbering: { reference: "bullet-list", level: 0 },
children: [new TextRun("First bullet point")]
}),
new Paragraph({
numbering: { reference: "bullet-list", level: 0 },
children: [new TextRun("Second bullet point")]
})
]
})
]
})
]
})
```
**IMPORTANT: Table Width & Borders**
- Use BOTH `columnWidths: [width1, width2, ...]` array AND `width: { size: X, type: WidthType.DXA }` on each cell
- Values in DXA (twentieths of a point): 1440 = 1 inch, Letter usable width = 9360 DXA (with 1" margins)
- Apply borders to individual `TableCell` elements, NOT the `Table` itself
**Precomputed Column Widths (Letter size with 1" margins = 9360 DXA total):**
- **2 columns:** `columnWidths: [4680, 4680]` (equal width)
- **3 columns:** `columnWidths: [3120, 3120, 3120]` (equal width)
## Links & Navigation
```javascript
// TOC (requires headings) - CRITICAL: Use HeadingLevel only, NOT custom styles
// ❌ WRONG: new Paragraph({ heading: HeadingLevel.HEADING_1, style: "customHeader", children: [new TextRun("Title")] })
// ✅ CORRECT: new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] })
new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" }),
// External link
new Paragraph({
children: [new ExternalHyperlink({
children: [new TextRun({ text: "Google", style: "Hyperlink" })],
link: "https://www.google.com"
})]
}),
// Internal link & bookmark
new Paragraph({
children: [new InternalHyperlink({
children: [new TextRun({ text: "Go to Section", style: "Hyperlink" })],
anchor: "section1"
})]
}),
new Paragraph({
children: [new TextRun("Section Content")],
bookmark: { id: "section1", name: "section1" }
}),
```
## Images & Media
```javascript
// Basic image with sizing & positioning
// CRITICAL: Always specify 'type' parameter - it's REQUIRED for ImageRun
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new ImageRun({
type: "png", // NEW REQUIREMENT: Must specify image type (png, jpg, jpeg, gif, bmp, svg)
data: fs.readFileSync("image.png"),
transformation: { width: 200, height: 150, rotation: 0 }, // rotation in degrees
altText: { title: "Logo", description: "Company logo", name: "Name" } // IMPORTANT: All three fields are required
})]
})
```
## Page Breaks
```javascript
// Manual page break
new Paragraph({ children: [new PageBreak()] }),
// Page break before paragraph
new Paragraph({
pageBreakBefore: true,
children: [new TextRun("This starts on a new page")]
})
// ⚠️ CRITICAL: NEVER use PageBreak standalone - it will create invalid XML that Word cannot open
// ❌ WRONG: new PageBreak()
// ✅ CORRECT: new Paragraph({ children: [new PageBreak()] })
```
## Headers/Footers & Page Setup
```javascript
const doc = new Document({
sections: [{
properties: {
page: {
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 }, // 1440 = 1 inch
size: { orientation: PageOrientation.LANDSCAPE },
pageNumbers: { start: 1, formatType: "decimal" } // "upperRoman", "lowerRoman", "upperLetter", "lowerLetter"
}
},
headers: {
default: new Header({ children: [new Paragraph({
alignment: AlignmentType.RIGHT,
children: [new TextRun("Header Text")]
})] })
},
footers: {
default: new Footer({ children: [new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] }), new TextRun(" of "), new TextRun({ children: [PageNumber.TOTAL_PAGES] })]
})] })
},
children: [/* content */]
}]
});
```
## Tabs
```javascript
new Paragraph({
tabStops: [
{ type: TabStopType.LEFT, position: TabStopPosition.MAX / 4 },
{ type: TabStopType.CENTER, position: TabStopPosition.MAX / 2 },
{ type: TabStopType.RIGHT, position: TabStopPosition.MAX * 3 / 4 }
],
children: [new TextRun("Left\tCenter\tRight")]
})
```
## Constants & Quick Reference
- **Underlines:** `SINGLE`, `DOUBLE`, `WAVY`, `DASH`
- **Borders:** `SINGLE`, `DOUBLE`, `DASHED`, `DOTTED`
- **Numbering:** `DECIMAL` (1,2,3), `UPPER_ROMAN` (I,II,III), `LOWER_LETTER` (a,b,c)
- **Tabs:** `LEFT`, `CENTER`, `RIGHT`, `DECIMAL`
- **Symbols:** `"2022"` (•), `"00A9"` (©), `"00AE"` (®), `"2122"` (™), `"00B0"` (°), `"F070"` (✓), `"F0FC"` (✗)
## Critical Issues & Common Mistakes
- **CRITICAL: PageBreak must ALWAYS be inside a Paragraph** - standalone PageBreak creates invalid XML that Word cannot open
- **ALWAYS use ShadingType.CLEAR for table cell shading** - Never use ShadingType.SOLID (causes black background).
- Measurements in DXA (1440 = 1 inch) | Each table cell needs ≥1 Paragraph | TOC requires HeadingLevel styles only
- **ALWAYS use custom styles** with Arial font for professional appearance and proper visual hierarchy
- **ALWAYS set a default font** using `styles.default.document.run.font` - Arial recommended
- **ALWAYS use columnWidths array for tables** + individual cell widths for compatibility
- **NEVER use unicode symbols for bullets** - always use proper numbering configuration with `LevelFormat.BULLET` constant (NOT the string "bullet")
- **NEVER use \n for line breaks anywhere** - always use separate Paragraph elements for each line
- **ALWAYS use TextRun objects within Paragraph children** - never use text property directly on Paragraph
- **CRITICAL for images**: ImageRun REQUIRES `type` parameter - always specify "png", "jpg", "jpeg", "gif", "bmp", or "svg"
- **CRITICAL for bullets**: Must use `LevelFormat.BULLET` constant, not string "bullet", and include `text: "•"` for the bullet character
- **CRITICAL for numbering**: Each numbering reference creates an INDEPENDENT list. Same reference = continues numbering (1,2,3 then 4,5,6). Different reference = restarts at 1 (1,2,3 then 1,2,3). Use unique reference names for each separate numbered section!
- **CRITICAL for TOC**: When using TableOfContents, headings must use HeadingLevel ONLY - do NOT add custom styles to heading paragraphs or TOC will break
- **Tables**: Set `columnWidths` array + individual cell widths, apply borders to cells not table
- **Set table margins at TABLE level** for consistent cell padding (avoids repetition per cell)
-610
View File
@@ -1,610 +0,0 @@
# Office Open XML Technical Reference
**Important: Read this entire document before starting.** This document covers:
- [Technical Guidelines](#technical-guidelines) - Schema compliance rules and validation requirements
- [Document Content Patterns](#document-content-patterns) - XML patterns for headings, lists, tables, formatting, etc.
- [Document Library (Python)](#document-library-python) - Recommended approach for OOXML manipulation with automatic infrastructure setup
- [Tracked Changes (Redlining)](#tracked-changes-redlining) - XML patterns for implementing tracked changes
## Technical Guidelines
### Schema Compliance
- **Element ordering in `<w:pPr>`**: `<w:pStyle>`, `<w:numPr>`, `<w:spacing>`, `<w:ind>`, `<w:jc>`
- **Whitespace**: Add `xml:space='preserve'` to `<w:t>` elements with leading/trailing spaces
- **Unicode**: Escape characters in ASCII content: `"` becomes `&#8220;`
- **Character encoding reference**: Curly quotes `""` become `&#8220;&#8221;`, apostrophe `'` becomes `&#8217;`, em-dash `—` becomes `&#8212;`
- **Tracked changes**: Use `<w:del>` and `<w:ins>` tags with `w:author="Claude"` outside `<w:r>` elements
- **Critical**: `<w:ins>` closes with `</w:ins>`, `<w:del>` closes with `</w:del>` - never mix
- **RSIDs must be 8-digit hex**: Use values like `00AB1234` (only 0-9, A-F characters)
- **trackRevisions placement**: Add `<w:trackRevisions/>` after `<w:proofState>` in settings.xml
- **Images**: Add to `word/media/`, reference in `document.xml`, set dimensions to prevent overflow
## Document Content Patterns
### Basic Structure
```xml
<w:p>
<w:r><w:t>Text content</w:t></w:r>
</w:p>
```
### Headings and Styles
```xml
<w:p>
<w:pPr>
<w:pStyle w:val="Title"/>
<w:jc w:val="center"/>
</w:pPr>
<w:r><w:t>Document Title</w:t></w:r>
</w:p>
<w:p>
<w:pPr><w:pStyle w:val="Heading2"/></w:pPr>
<w:r><w:t>Section Heading</w:t></w:r>
</w:p>
```
### Text Formatting
```xml
<!-- Bold -->
<w:r><w:rPr><w:b/><w:bCs/></w:rPr><w:t>Bold</w:t></w:r>
<!-- Italic -->
<w:r><w:rPr><w:i/><w:iCs/></w:rPr><w:t>Italic</w:t></w:r>
<!-- Underline -->
<w:r><w:rPr><w:u w:val="single"/></w:rPr><w:t>Underlined</w:t></w:r>
<!-- Highlight -->
<w:r><w:rPr><w:highlight w:val="yellow"/></w:rPr><w:t>Highlighted</w:t></w:r>
```
### Lists
```xml
<!-- Numbered list -->
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr><w:ilvl w:val="0"/><w:numId w:val="1"/></w:numPr>
<w:spacing w:before="240"/>
</w:pPr>
<w:r><w:t>First item</w:t></w:r>
</w:p>
<!-- Restart numbered list at 1 - use different numId -->
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr><w:ilvl w:val="0"/><w:numId w:val="2"/></w:numPr>
<w:spacing w:before="240"/>
</w:pPr>
<w:r><w:t>New list item 1</w:t></w:r>
</w:p>
<!-- Bullet list (level 2) -->
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr><w:ilvl w:val="1"/><w:numId w:val="1"/></w:numPr>
<w:spacing w:before="240"/>
<w:ind w:left="900"/>
</w:pPr>
<w:r><w:t>Bullet item</w:t></w:r>
</w:p>
```
### Tables
```xml
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="0" w:type="auto"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="4675"/><w:gridCol w:w="4675"/>
</w:tblGrid>
<w:tr>
<w:tc>
<w:tcPr><w:tcW w:w="4675" w:type="dxa"/></w:tcPr>
<w:p><w:r><w:t>Cell 1</w:t></w:r></w:p>
</w:tc>
<w:tc>
<w:tcPr><w:tcW w:w="4675" w:type="dxa"/></w:tcPr>
<w:p><w:r><w:t>Cell 2</w:t></w:r></w:p>
</w:tc>
</w:tr>
</w:tbl>
```
### Layout
```xml
<!-- Page break before new section (common pattern) -->
<w:p>
<w:r>
<w:br w:type="page"/>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t>New Section Title</w:t>
</w:r>
</w:p>
<!-- Centered paragraph -->
<w:p>
<w:pPr>
<w:spacing w:before="240" w:after="0"/>
<w:jc w:val="center"/>
</w:pPr>
<w:r><w:t>Centered text</w:t></w:r>
</w:p>
<!-- Font change - paragraph level (applies to all runs) -->
<w:p>
<w:pPr>
<w:rPr><w:rFonts w:ascii="Courier New" w:hAnsi="Courier New"/></w:rPr>
</w:pPr>
<w:r><w:t>Monospace text</w:t></w:r>
</w:p>
<!-- Font change - run level (specific to this text) -->
<w:p>
<w:r>
<w:rPr><w:rFonts w:ascii="Courier New" w:hAnsi="Courier New"/></w:rPr>
<w:t>This text is Courier New</w:t>
</w:r>
<w:r><w:t> and this text uses default font</w:t></w:r>
</w:p>
```
## File Updates
When adding content, update these files:
**`word/_rels/document.xml.rels`:**
```xml
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png"/>
```
**`[Content_Types].xml`:**
```xml
<Default Extension="png" ContentType="image/png"/>
<Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>
```
### Images
**CRITICAL**: Calculate dimensions to prevent page overflow and maintain aspect ratio.
```xml
<!-- Minimal required structure -->
<w:p>
<w:r>
<w:drawing>
<wp:inline>
<wp:extent cx="2743200" cy="1828800"/>
<wp:docPr id="1" name="Picture 1"/>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr>
<pic:cNvPr id="0" name="image1.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId5"/>
<!-- Add for stretch fill with aspect ratio preservation -->
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:ext cx="2743200" cy="1828800"/>
</a:xfrm>
<a:prstGeom prst="rect"/>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>
```
### Links (Hyperlinks)
**IMPORTANT**: All hyperlinks (both internal and external) require the Hyperlink style to be defined in styles.xml. Without this style, links will look like regular text instead of blue underlined clickable links.
**External Links:**
```xml
<!-- In document.xml -->
<w:hyperlink r:id="rId5">
<w:r>
<w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr>
<w:t>Link Text</w:t>
</w:r>
</w:hyperlink>
<!-- In word/_rels/document.xml.rels -->
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="https://www.example.com/" TargetMode="External"/>
```
**Internal Links:**
```xml
<!-- Link to bookmark -->
<w:hyperlink w:anchor="myBookmark">
<w:r>
<w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr>
<w:t>Link Text</w:t>
</w:r>
</w:hyperlink>
<!-- Bookmark target -->
<w:bookmarkStart w:id="0" w:name="myBookmark"/>
<w:r><w:t>Target content</w:t></w:r>
<w:bookmarkEnd w:id="0"/>
```
**Hyperlink Style (required in styles.xml):**
```xml
<w:style w:type="character" w:styleId="Hyperlink">
<w:name w:val="Hyperlink"/>
<w:basedOn w:val="DefaultParagraphFont"/>
<w:uiPriority w:val="99"/>
<w:unhideWhenUsed/>
<w:rPr>
<w:color w:val="467886" w:themeColor="hyperlink"/>
<w:u w:val="single"/>
</w:rPr>
</w:style>
```
## Document Library (Python)
Use the Document class from `scripts/document.py` for all tracked changes and comments. It automatically handles infrastructure setup (people.xml, RSIDs, settings.xml, comment files, relationships, content types). Only use direct XML manipulation for complex scenarios not supported by the library.
**Working with Unicode and Entities:**
- **Searching**: Both entity notation and Unicode characters work - `contains="&#8220;Company"` and `contains="\u201cCompany"` find the same text
- **Replacing**: Use either entities (`&#8220;`) or Unicode (`\u201c`) - both work and will be converted appropriately based on the file's encoding (ascii → entities, utf-8 → Unicode)
### Initialization
**Find the docx skill root** (directory containing `scripts/` and `ooxml/`):
```bash
# Search for document.py to locate the skill root
# Note: /mnt/skills is used here as an example; check your context for the actual location
find /mnt/skills -name "document.py" -path "*/docx/scripts/*" 2>/dev/null | head -1
# Example output: /mnt/skills/word-document-processor/scripts/document.py
# Skill root is: /mnt/skills/word-document-processor
```
**Run your script with PYTHONPATH** set to the docx skill root:
```bash
PYTHONPATH=/mnt/skills/word-document-processor python your_script.py
```
**In your script**, import from the skill root:
```python
from scripts.document import Document, DocxXMLEditor
# Basic initialization (automatically creates temp copy and sets up infrastructure)
doc = Document('unpacked')
# Customize author and initials
doc = Document('unpacked', author="John Doe", initials="JD")
# Enable track revisions mode
doc = Document('unpacked', track_revisions=True)
# Specify custom RSID (auto-generated if not provided)
doc = Document('unpacked', rsid="07DC5ECB")
```
### Creating Tracked Changes
**CRITICAL**: Only mark text that actually changes. Keep ALL unchanged text outside `<w:del>`/`<w:ins>` tags. Marking unchanged text makes edits unprofessional and harder to review.
**Attribute Handling**: The Document class auto-injects attributes (w:id, w:date, w:rsidR, w:rsidDel, w16du:dateUtc, xml:space) into new elements. When preserving unchanged text from the original document, copy the original `<w:r>` element with its existing attributes to maintain document integrity.
**Method Selection Guide**:
- **Adding your own changes to regular text**: Use `replace_node()` with `<w:del>`/`<w:ins>` tags, or `suggest_deletion()` for removing entire `<w:r>` or `<w:p>` elements
- **Partially modifying another author's tracked change**: Use `replace_node()` to nest your changes inside their `<w:ins>`/`<w:del>`
- **Completely rejecting another author's insertion**: Use `revert_insertion()` on the `<w:ins>` element (NOT `suggest_deletion()`)
- **Completely rejecting another author's deletion**: Use `revert_deletion()` on the `<w:del>` element to restore deleted content using tracked changes
```python
# Minimal edit - change one word: "The report is monthly" → "The report is quarterly"
# Original: <w:r w:rsidR="00AB12CD"><w:rPr><w:rFonts w:ascii="Calibri"/></w:rPr><w:t>The report is monthly</w:t></w:r>
node = doc["word/document.xml"].get_node(tag="w:r", contains="The report is monthly")
rpr = tags[0].toxml() if (tags := node.getElementsByTagName("w:rPr")) else ""
replacement = f'<w:r w:rsidR="00AB12CD">{rpr}<w:t>The report is </w:t></w:r><w:del><w:r>{rpr}<w:delText>monthly</w:delText></w:r></w:del><w:ins><w:r>{rpr}<w:t>quarterly</w:t></w:r></w:ins>'
doc["word/document.xml"].replace_node(node, replacement)
# Minimal edit - change number: "within 30 days" → "within 45 days"
# Original: <w:r w:rsidR="00XYZ789"><w:rPr><w:rFonts w:ascii="Calibri"/></w:rPr><w:t>within 30 days</w:t></w:r>
node = doc["word/document.xml"].get_node(tag="w:r", contains="within 30 days")
rpr = tags[0].toxml() if (tags := node.getElementsByTagName("w:rPr")) else ""
replacement = f'<w:r w:rsidR="00XYZ789">{rpr}<w:t>within </w:t></w:r><w:del><w:r>{rpr}<w:delText>30</w:delText></w:r></w:del><w:ins><w:r>{rpr}<w:t>45</w:t></w:r></w:ins><w:r w:rsidR="00XYZ789">{rpr}<w:t> days</w:t></w:r>'
doc["word/document.xml"].replace_node(node, replacement)
# Complete replacement - preserve formatting even when replacing all text
node = doc["word/document.xml"].get_node(tag="w:r", contains="apple")
rpr = tags[0].toxml() if (tags := node.getElementsByTagName("w:rPr")) else ""
replacement = f'<w:del><w:r>{rpr}<w:delText>apple</w:delText></w:r></w:del><w:ins><w:r>{rpr}<w:t>banana orange</w:t></w:r></w:ins>'
doc["word/document.xml"].replace_node(node, replacement)
# Insert new content (no attributes needed - auto-injected)
node = doc["word/document.xml"].get_node(tag="w:r", contains="existing text")
doc["word/document.xml"].insert_after(node, '<w:ins><w:r><w:t>new text</w:t></w:r></w:ins>')
# Partially delete another author's insertion
# Original: <w:ins w:author="Jane Smith" w:date="..."><w:r><w:t>quarterly financial report</w:t></w:r></w:ins>
# Goal: Delete only "financial" to make it "quarterly report"
node = doc["word/document.xml"].get_node(tag="w:ins", attrs={"w:id": "5"})
# IMPORTANT: Preserve w:author="Jane Smith" on the outer <w:ins> to maintain authorship
replacement = '''<w:ins w:author="Jane Smith" w:date="2025-01-15T10:00:00Z">
<w:r><w:t>quarterly </w:t></w:r>
<w:del><w:r><w:delText>financial </w:delText></w:r></w:del>
<w:r><w:t>report</w:t></w:r>
</w:ins>'''
doc["word/document.xml"].replace_node(node, replacement)
# Change part of another author's insertion
# Original: <w:ins w:author="Jane Smith"><w:r><w:t>in silence, safe and sound</w:t></w:r></w:ins>
# Goal: Change "safe and sound" to "soft and unbound"
node = doc["word/document.xml"].get_node(tag="w:ins", attrs={"w:id": "8"})
replacement = f'''<w:ins w:author="Jane Smith" w:date="2025-01-15T10:00:00Z">
<w:r><w:t>in silence, </w:t></w:r>
</w:ins>
<w:ins>
<w:r><w:t>soft and unbound</w:t></w:r>
</w:ins>
<w:ins w:author="Jane Smith" w:date="2025-01-15T10:00:00Z">
<w:del><w:r><w:delText>safe and sound</w:delText></w:r></w:del>
</w:ins>'''
doc["word/document.xml"].replace_node(node, replacement)
# Delete entire run (use only when deleting all content; use replace_node for partial deletions)
node = doc["word/document.xml"].get_node(tag="w:r", contains="text to delete")
doc["word/document.xml"].suggest_deletion(node)
# Delete entire paragraph (in-place, handles both regular and numbered list paragraphs)
para = doc["word/document.xml"].get_node(tag="w:p", contains="paragraph to delete")
doc["word/document.xml"].suggest_deletion(para)
# Add new numbered list item
target_para = doc["word/document.xml"].get_node(tag="w:p", contains="existing list item")
pPr = tags[0].toxml() if (tags := target_para.getElementsByTagName("w:pPr")) else ""
new_item = f'<w:p>{pPr}<w:r><w:t>New item</w:t></w:r></w:p>'
tracked_para = DocxXMLEditor.suggest_paragraph(new_item)
doc["word/document.xml"].insert_after(target_para, tracked_para)
# Optional: add spacing paragraph before content for better visual separation
# spacing = DocxXMLEditor.suggest_paragraph('<w:p><w:pPr><w:pStyle w:val="ListParagraph"/></w:pPr></w:p>')
# doc["word/document.xml"].insert_after(target_para, spacing + tracked_para)
```
### Adding Comments
```python
# Add comment spanning two existing tracked changes
# Note: w:id is auto-generated. Only search by w:id if you know it from XML inspection
start_node = doc["word/document.xml"].get_node(tag="w:del", attrs={"w:id": "1"})
end_node = doc["word/document.xml"].get_node(tag="w:ins", attrs={"w:id": "2"})
doc.add_comment(start=start_node, end=end_node, text="Explanation of this change")
# Add comment on a paragraph
para = doc["word/document.xml"].get_node(tag="w:p", contains="paragraph text")
doc.add_comment(start=para, end=para, text="Comment on this paragraph")
# Add comment on newly created tracked change
# First create the tracked change
node = doc["word/document.xml"].get_node(tag="w:r", contains="old")
new_nodes = doc["word/document.xml"].replace_node(
node,
'<w:del><w:r><w:delText>old</w:delText></w:r></w:del><w:ins><w:r><w:t>new</w:t></w:r></w:ins>'
)
# Then add comment on the newly created elements
# new_nodes[0] is the <w:del>, new_nodes[1] is the <w:ins>
doc.add_comment(start=new_nodes[0], end=new_nodes[1], text="Changed old to new per requirements")
# Reply to existing comment
doc.reply_to_comment(parent_comment_id=0, text="I agree with this change")
```
### Rejecting Tracked Changes
**IMPORTANT**: Use `revert_insertion()` to reject insertions and `revert_deletion()` to restore deletions using tracked changes. Use `suggest_deletion()` only for regular unmarked content.
```python
# Reject insertion (wraps it in deletion)
# Use this when another author inserted text that you want to delete
ins = doc["word/document.xml"].get_node(tag="w:ins", attrs={"w:id": "5"})
nodes = doc["word/document.xml"].revert_insertion(ins) # Returns [ins]
# Reject deletion (creates insertion to restore deleted content)
# Use this when another author deleted text that you want to restore
del_elem = doc["word/document.xml"].get_node(tag="w:del", attrs={"w:id": "3"})
nodes = doc["word/document.xml"].revert_deletion(del_elem) # Returns [del_elem, new_ins]
# Reject all insertions in a paragraph
para = doc["word/document.xml"].get_node(tag="w:p", contains="paragraph text")
nodes = doc["word/document.xml"].revert_insertion(para) # Returns [para]
# Reject all deletions in a paragraph
para = doc["word/document.xml"].get_node(tag="w:p", contains="paragraph text")
nodes = doc["word/document.xml"].revert_deletion(para) # Returns [para]
```
### Inserting Images
**CRITICAL**: The Document class works with a temporary copy at `doc.unpacked_path`. Always copy images to this temp directory, not the original unpacked folder.
```python
from PIL import Image
import shutil, os
# Initialize document first
doc = Document('unpacked')
# Copy image and calculate full-width dimensions with aspect ratio
media_dir = os.path.join(doc.unpacked_path, 'word/media')
os.makedirs(media_dir, exist_ok=True)
shutil.copy('image.png', os.path.join(media_dir, 'image1.png'))
img = Image.open(os.path.join(media_dir, 'image1.png'))
width_emus = int(6.5 * 914400) # 6.5" usable width, 914400 EMUs/inch
height_emus = int(width_emus * img.size[1] / img.size[0])
# Add relationship and content type
rels_editor = doc['word/_rels/document.xml.rels']
next_rid = rels_editor.get_next_rid()
rels_editor.append_to(rels_editor.dom.documentElement,
f'<Relationship Id="{next_rid}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png"/>')
doc['[Content_Types].xml'].append_to(doc['[Content_Types].xml'].dom.documentElement,
'<Default Extension="png" ContentType="image/png"/>')
# Insert image
node = doc["word/document.xml"].get_node(tag="w:p", line_number=100)
doc["word/document.xml"].insert_after(node, f'''<w:p>
<w:r>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="{width_emus}" cy="{height_emus}"/>
<wp:docPr id="1" name="Picture 1"/>
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:nvPicPr><pic:cNvPr id="1" name="image1.png"/><pic:cNvPicPr/></pic:nvPicPr>
<pic:blipFill><a:blip r:embed="{next_rid}"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill>
<pic:spPr><a:xfrm><a:ext cx="{width_emus}" cy="{height_emus}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:r>
</w:p>''')
```
### Getting Nodes
```python
# By text content
node = doc["word/document.xml"].get_node(tag="w:p", contains="specific text")
# By line range
para = doc["word/document.xml"].get_node(tag="w:p", line_number=range(100, 150))
# By attributes
node = doc["word/document.xml"].get_node(tag="w:del", attrs={"w:id": "1"})
# By exact line number (must be line number where tag opens)
para = doc["word/document.xml"].get_node(tag="w:p", line_number=42)
# Combine filters
node = doc["word/document.xml"].get_node(tag="w:r", line_number=range(40, 60), contains="text")
# Disambiguate when text appears multiple times - add line_number range
node = doc["word/document.xml"].get_node(tag="w:r", contains="Section", line_number=range(2400, 2500))
```
### Saving
```python
# Save with automatic validation (copies back to original directory)
doc.save() # Validates by default, raises error if validation fails
# Save to different location
doc.save('modified-unpacked')
# Skip validation (debugging only - needing this in production indicates XML issues)
doc.save(validate=False)
```
### Direct DOM Manipulation
For complex scenarios not covered by the library:
```python
# Access any XML file
editor = doc["word/document.xml"]
editor = doc["word/comments.xml"]
# Direct DOM access (defusedxml.minidom.Document)
node = doc["word/document.xml"].get_node(tag="w:p", line_number=5)
parent = node.parentNode
parent.removeChild(node)
parent.appendChild(node) # Move to end
# General document manipulation (without tracked changes)
old_node = doc["word/document.xml"].get_node(tag="w:p", contains="original text")
doc["word/document.xml"].replace_node(old_node, "<w:p><w:r><w:t>replacement text</w:t></w:r></w:p>")
# Multiple insertions - use return value to maintain order
node = doc["word/document.xml"].get_node(tag="w:r", line_number=100)
nodes = doc["word/document.xml"].insert_after(node, "<w:r><w:t>A</w:t></w:r>")
nodes = doc["word/document.xml"].insert_after(nodes[-1], "<w:r><w:t>B</w:t></w:r>")
nodes = doc["word/document.xml"].insert_after(nodes[-1], "<w:r><w:t>C</w:t></w:r>")
# Results in: original_node, A, B, C
```
## Tracked Changes (Redlining)
**Use the Document class above for all tracked changes.** The patterns below are for reference when constructing replacement XML strings.
### Validation Rules
The validator checks that the document text matches the original after reverting Claude's changes. This means:
- **NEVER modify text inside another author's `<w:ins>` or `<w:del>` tags**
- **ALWAYS use nested deletions** to remove another author's insertions
- **Every edit must be properly tracked** with `<w:ins>` or `<w:del>` tags
### Tracked Change Patterns
**CRITICAL RULES**:
1. Never modify the content inside another author's tracked changes. Always use nested deletions.
2. **XML Structure**: Always place `<w:del>` and `<w:ins>` at paragraph level containing complete `<w:r>` elements. Never nest inside `<w:r>` elements - this creates invalid XML that breaks document processing.
**Text Insertion:**
```xml
<w:ins w:id="1" w:author="Claude" w:date="2025-07-30T23:05:00Z" w16du:dateUtc="2025-07-31T06:05:00Z">
<w:r w:rsidR="00792858">
<w:t>inserted text</w:t>
</w:r>
</w:ins>
```
**Text Deletion:**
```xml
<w:del w:id="2" w:author="Claude" w:date="2025-07-30T23:05:00Z" w16du:dateUtc="2025-07-31T06:05:00Z">
<w:r w:rsidDel="00792858">
<w:delText>deleted text</w:delText>
</w:r>
</w:del>
```
**Deleting Another Author's Insertion (MUST use nested structure):**
```xml
<!-- Nest deletion inside the original insertion -->
<w:ins w:author="Jane Smith" w:id="16">
<w:del w:author="Claude" w:id="40">
<w:r><w:delText>monthly</w:delText></w:r>
</w:del>
</w:ins>
<w:ins w:author="Claude" w:id="41">
<w:r><w:t>weekly</w:t></w:r>
</w:ins>
```
**Restoring Another Author's Deletion:**
```xml
<!-- Leave their deletion unchanged, add new insertion after it -->
<w:del w:author="Jane Smith" w:id="50">
<w:r><w:delText>within 30 days</w:delText></w:r>
</w:del>
<w:ins w:author="Claude" w:id="51">
<w:r><w:t>within 30 days</w:t></w:r>
</w:ins>
```
File diff suppressed because it is too large Load Diff
@@ -1,146 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:complexType name="CT_ShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ConnectorNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Connector">
<xsd:sequence>
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicFrameNonVisual" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ObjectChoices">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_MarkerCoordinate">
<xsd:restriction base="xsd:double">
<xsd:minInclusive value="0.0"/>
<xsd:maxInclusive value="1.0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="x" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
<xsd:element name="y" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="to" type="CT_Marker"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AbsSizeAnchor">
<xsd:sequence>
<xsd:element name="from" type="CT_Marker"/>
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
<xsd:group ref="EG_ObjectChoices"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_Anchor">
<xsd:choice>
<xsd:element name="relSizeAnchor" type="CT_RelSizeAnchor"/>
<xsd:element name="absSizeAnchor" type="CT_AbsSizeAnchor"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Drawing">
<xsd:sequence>
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
File diff suppressed because it is too large Load Diff
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:element name="lockedCanvas" type="a:CT_GvmlGroupShape"/>
</xsd:schema>
File diff suppressed because it is too large Load Diff
@@ -1,23 +0,0 @@
<?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>
@@ -1,185 +0,0 @@
<?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>
@@ -1,287 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:dpct="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
schemaLocation="dml-main.xsd"/>
<xsd:import schemaLocation="wml.xsd"
namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/picture"
schemaLocation="dml-picture.xsd"/>
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
schemaLocation="shared-relationshipReference.xsd"/>
<xsd:complexType name="CT_EffectExtent">
<xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
<xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_WrapDistance">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:complexType name="CT_Inline">
<xsd:sequence>
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="0" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:simpleType name="ST_WrapText">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="bothSides"/>
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="largest"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_WrapPath">
<xsd:sequence>
<xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
<xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapNone"/>
<xsd:complexType name="CT_WrapSquare">
<xsd:sequence>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapTight">
<xsd:sequence>
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapThrough">
<xsd:sequence>
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_WrapTopBottom">
<xsd:sequence>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_WrapType">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="wrapNone" type="CT_WrapNone" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapSquare" type="CT_WrapSquare" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapTight" type="CT_WrapTight" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapThrough" type="CT_WrapThrough" minOccurs="1" maxOccurs="1"/>
<xsd:element name="wrapTopAndBottom" type="CT_WrapTopBottom" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:simpleType name="ST_PositionOffset">
<xsd:restriction base="xsd:int"/>
</xsd:simpleType>
<xsd:simpleType name="ST_AlignH">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RelFromH">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="column"/>
<xsd:enumeration value="character"/>
<xsd:enumeration value="leftMargin"/>
<xsd:enumeration value="rightMargin"/>
<xsd:enumeration value="insideMargin"/>
<xsd:enumeration value="outsideMargin"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_PosH">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="align" type="ST_AlignH" minOccurs="1" maxOccurs="1"/>
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="relativeFrom" type="ST_RelFromH" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_AlignV">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="top"/>
<xsd:enumeration value="bottom"/>
<xsd:enumeration value="center"/>
<xsd:enumeration value="inside"/>
<xsd:enumeration value="outside"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_RelFromV">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="paragraph"/>
<xsd:enumeration value="line"/>
<xsd:enumeration value="topMargin"/>
<xsd:enumeration value="bottomMargin"/>
<xsd:enumeration value="insideMargin"/>
<xsd:enumeration value="outsideMargin"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_PosV">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="align" type="ST_AlignV" minOccurs="1" maxOccurs="1"/>
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="relativeFrom" type="ST_RelFromV" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Anchor">
<xsd:sequence>
<xsd:element name="simplePos" type="a:CT_Point2D"/>
<xsd:element name="positionH" type="CT_PosH"/>
<xsd:element name="positionV" type="CT_PosV"/>
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
<xsd:group ref="EG_WrapType"/>
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
minOccurs="0" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
<xsd:attribute name="simplePos" type="xsd:boolean"/>
<xsd:attribute name="relativeHeight" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="behindDoc" type="xsd:boolean" use="required"/>
<xsd:attribute name="locked" type="xsd:boolean" use="required"/>
<xsd:attribute name="layoutInCell" type="xsd:boolean" use="required"/>
<xsd:attribute name="hidden" type="xsd:boolean" use="optional"/>
<xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_TxbxContent">
<xsd:group ref="w:EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/>
</xsd:complexType>
<xsd:complexType name="CT_TextboxInfo">
<xsd:sequence>
<xsd:element name="txbxContent" type="CT_TxbxContent" minOccurs="1" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:unsignedShort" use="optional" default="0"/>
</xsd:complexType>
<xsd:complexType name="CT_LinkedTextboxInformation">
<xsd:sequence>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:unsignedShort" use="required"/>
<xsd:attribute name="seq" type="xsd:unsignedShort" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingShape">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="cNvCnPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
maxOccurs="1"/>
</xsd:choice>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="txbx" type="CT_TextboxInfo" minOccurs="1" maxOccurs="1"/>
<xsd:element name="linkedTxbx" type="CT_LinkedTextboxInformation" minOccurs="1"
maxOccurs="1"/>
</xsd:choice>
<xsd:element name="bodyPr" type="a:CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="normalEastAsianFlow" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicFrame">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
<xsd:element name="cNvFrPr" type="a:CT_NonVisualGraphicFrameProperties" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingContentPartNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cNvContentPartPr" type="a:CT_NonVisualContentPartProperties" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingContentPart">
<xsd:sequence>
<xsd:element name="nvContentPartPr" type="CT_WordprocessingContentPartNonVisual" minOccurs="0" maxOccurs="1"/>
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional"/>
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingGroup">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
maxOccurs="1"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="wsp"/>
<xsd:element name="grpSp" type="CT_WordprocessingGroup"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
<xsd:element ref="dpct:pic"/>
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
</xsd:choice>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_WordprocessingCanvas">
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="bg" type="a:CT_BackgroundFormatting" minOccurs="0" maxOccurs="1"/>
<xsd:element name="whole" type="a:CT_WholeE2oFormatting" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="wsp"/>
<xsd:element ref="dpct:pic"/>
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
<xsd:element ref="wgp"/>
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
</xsd:choice>
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="wpc" type="CT_WordprocessingCanvas"/>
<xsd:element name="wgp" type="CT_WordprocessingGroup"/>
<xsd:element name="wsp" type="CT_WordprocessingShape"/>
<xsd:element name="inline" type="CT_Inline"/>
<xsd:element name="anchor" type="CT_Anchor"/>
</xsd:schema>
File diff suppressed because it is too large Load Diff
@@ -1,28 +0,0 @@
<?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>
@@ -1,144 +0,0 @@
<?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>
@@ -1,174 +0,0 @@
<?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>
@@ -1,25 +0,0 @@
<?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>
@@ -1,18 +0,0 @@
<?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>
@@ -1,59 +0,0 @@
<?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>
@@ -1,56 +0,0 @@
<?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>
@@ -1,195 +0,0 @@
<?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>
@@ -1,582 +0,0 @@
<?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>
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
elementFormDefault="qualified"
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
blockDefault="#all">
<xsd:simpleType name="ST_RelationshipId">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:attribute name="id" type="ST_RelationshipId"/>
<xsd:attribute name="embed" type="ST_RelationshipId"/>
<xsd:attribute name="link" type="ST_RelationshipId"/>
<xsd:attribute name="dm" type="ST_RelationshipId" default=""/>
<xsd:attribute name="lo" type="ST_RelationshipId" default=""/>
<xsd:attribute name="qs" type="ST_RelationshipId" default=""/>
<xsd:attribute name="cs" type="ST_RelationshipId" default=""/>
<xsd:attribute name="blip" type="ST_RelationshipId" default=""/>
<xsd:attribute name="pict" type="ST_RelationshipId"/>
<xsd:attribute name="href" type="ST_RelationshipId"/>
<xsd:attribute name="topLeft" type="ST_RelationshipId"/>
<xsd:attribute name="topRight" type="ST_RelationshipId"/>
<xsd:attribute name="bottomLeft" type="ST_RelationshipId"/>
<xsd:attribute name="bottomRight" type="ST_RelationshipId"/>
</xsd:schema>
File diff suppressed because it is too large Load Diff
@@ -1,570 +0,0 @@
<?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>
@@ -1,509 +0,0 @@
<?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>
@@ -1,12 +0,0 @@
<?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>
@@ -1,108 +0,0 @@
<?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>
@@ -1,96 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:word"
targetNamespace="urn:schemas-microsoft-com:office:word" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="bordertop" type="CT_Border"/>
<xsd:element name="borderleft" type="CT_Border"/>
<xsd:element name="borderright" type="CT_Border"/>
<xsd:element name="borderbottom" type="CT_Border"/>
<xsd:complexType name="CT_Border">
<xsd:attribute name="type" type="ST_BorderType" use="optional"/>
<xsd:attribute name="width" type="xsd:positiveInteger" use="optional"/>
<xsd:attribute name="shadow" type="ST_BorderShadow" use="optional"/>
</xsd:complexType>
<xsd:element name="wrap" type="CT_Wrap"/>
<xsd:complexType name="CT_Wrap">
<xsd:attribute name="type" type="ST_WrapType" use="optional"/>
<xsd:attribute name="side" type="ST_WrapSide" use="optional"/>
<xsd:attribute name="anchorx" type="ST_HorizontalAnchor" use="optional"/>
<xsd:attribute name="anchory" type="ST_VerticalAnchor" use="optional"/>
</xsd:complexType>
<xsd:element name="anchorlock" type="CT_AnchorLock"/>
<xsd:complexType name="CT_AnchorLock"/>
<xsd:simpleType name="ST_BorderType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="single"/>
<xsd:enumeration value="thick"/>
<xsd:enumeration value="double"/>
<xsd:enumeration value="hairline"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="dotDash"/>
<xsd:enumeration value="dashDotDot"/>
<xsd:enumeration value="triple"/>
<xsd:enumeration value="thinThickSmall"/>
<xsd:enumeration value="thickThinSmall"/>
<xsd:enumeration value="thickBetweenThinSmall"/>
<xsd:enumeration value="thinThick"/>
<xsd:enumeration value="thickThin"/>
<xsd:enumeration value="thickBetweenThin"/>
<xsd:enumeration value="thinThickLarge"/>
<xsd:enumeration value="thickThinLarge"/>
<xsd:enumeration value="thickBetweenThinLarge"/>
<xsd:enumeration value="wave"/>
<xsd:enumeration value="doubleWave"/>
<xsd:enumeration value="dashedSmall"/>
<xsd:enumeration value="dashDotStroked"/>
<xsd:enumeration value="threeDEmboss"/>
<xsd:enumeration value="threeDEngrave"/>
<xsd:enumeration value="HTMLOutset"/>
<xsd:enumeration value="HTMLInset"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_BorderShadow">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="t"/>
<xsd:enumeration value="true"/>
<xsd:enumeration value="f"/>
<xsd:enumeration value="false"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_WrapType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="topAndBottom"/>
<xsd:enumeration value="square"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="tight"/>
<xsd:enumeration value="through"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_WrapSide">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="both"/>
<xsd:enumeration value="left"/>
<xsd:enumeration value="right"/>
<xsd:enumeration value="largest"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HorizontalAnchor">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="text"/>
<xsd:enumeration value="char"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_VerticalAnchor">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="margin"/>
<xsd:enumeration value="page"/>
<xsd:enumeration value="text"/>
<xsd:enumeration value="line"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
File diff suppressed because it is too large Load Diff
@@ -1,116 +0,0 @@
<?xml version='1.0'?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
<xs:annotation>
<xs:documentation>
See http://www.w3.org/XML/1998/namespace.html and
http://www.w3.org/TR/REC-xml for information about this namespace.
This schema document describes the XML namespace, in a form
suitable for import by other schema documents.
Note that local names in this namespace are intended to be defined
only by the World Wide Web Consortium or its subgroups. The
following names are currently defined in this namespace and should
not be used with conflicting semantics by any Working Group,
specification, or document instance:
base (as an attribute name): denotes an attribute whose value
provides a URI to be used as the base for interpreting any
relative URIs in the scope of the element on which it
appears; its value is inherited. This name is reserved
by virtue of its definition in the XML Base specification.
lang (as an attribute name): denotes an attribute whose value
is a language code for the natural language of the content of
any element; its value is inherited. This name is reserved
by virtue of its definition in the XML specification.
space (as an attribute name): denotes an attribute whose
value is a keyword indicating what whitespace processing
discipline is intended for the content of the element; its
value is inherited. This name is reserved by virtue of its
definition in the XML specification.
Father (in any context at all): denotes Jon Bosak, the chair of
the original XML Working Group. This name is reserved by
the following decision of the W3C XML Plenary and
XML Coordination groups:
In appreciation for his vision, leadership and dedication
the W3C XML Plenary on this 10th day of February, 2000
reserves for Jon Bosak in perpetuity the XML name
xml:Father
</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>This schema defines attributes and an attribute group
suitable for use by
schemas wishing to allow xml:base, xml:lang or xml:space attributes
on elements they define.
To enable this, such a schema must import this schema
for the XML namespace, e.g. as follows:
&lt;schema . . .>
. . .
&lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
Subsequently, qualified reference to any of the attributes
or the group defined below will have the desired effect, e.g.
&lt;type . . .>
. . .
&lt;attributeGroup ref="xml:specialAttrs"/>
will define a type which will schema-validate an instance
element with any of those attributes</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>In keeping with the XML Schema WG's standard versioning
policy, this schema document will persist at
http://www.w3.org/2001/03/xml.xsd.
At the date of issue it can also be found at
http://www.w3.org/2001/xml.xsd.
The schema document at that URI may however change in the future,
in order to remain compatible with the latest version of XML Schema
itself. In other words, if the XML Schema namespace changes, the version
of this document at
http://www.w3.org/2001/xml.xsd will change
accordingly; the version at
http://www.w3.org/2001/03/xml.xsd will not change.
</xs:documentation>
</xs:annotation>
<xs:attribute name="lang" type="xs:language">
<xs:annotation>
<xs:documentation>In due course, we should install the relevant ISO 2- and 3-letter
codes as the enumerated possible values . . .</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="space" default="preserve">
<xs:simpleType>
<xs:restriction base="xs:NCName">
<xs:enumeration value="default"/>
<xs:enumeration value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" type="xs:anyURI">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xmlbase/ for
information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup name="specialAttrs">
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/>
<xs:attribute ref="xml:space"/>
</xs:attributeGroup>
</xs:schema>
@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.openxmlformats.org/package/2006/content-types"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.openxmlformats.org/package/2006/content-types"
elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<xs:element name="Types" type="CT_Types"/>
<xs:element name="Default" type="CT_Default"/>
<xs:element name="Override" type="CT_Override"/>
<xs:complexType name="CT_Types">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Default"/>
<xs:element ref="Override"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="CT_Default">
<xs:attribute name="Extension" type="ST_Extension" use="required"/>
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
</xs:complexType>
<xs:complexType name="CT_Override">
<xs:attribute name="ContentType" type="ST_ContentType" use="required"/>
<xs:attribute name="PartName" type="xs:anyURI" use="required"/>
</xs:complexType>
<xs:simpleType name="ST_ContentType">
<xs:restriction base="xs:string">
<xs:pattern
value="(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+)|(&quot;(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}&#127;&quot;\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*&quot;))))*)"
/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ST_Extension">
<xs:restriction base="xs:string">
<xs:pattern
value="([!$&amp;'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:@]|[a-zA-Z0-9\-_~])+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
@@ -1,50 +0,0 @@
<?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>
@@ -1,49 +0,0 @@
<?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>
@@ -1,33 +0,0 @@
<?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>
-75
View File
@@ -1,75 +0,0 @@
<?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>
@@ -1,560 +0,0 @@
<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>
@@ -1,67 +0,0 @@
<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>
@@ -1,14 +0,0 @@
<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>
@@ -1,20 +0,0 @@
<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>
@@ -1,13 +0,0 @@
<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>
@@ -1,4 +0,0 @@
<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>
@@ -1,8 +0,0 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:w12="http://schemas.openxmlformats.org/wordprocessingml/2006/main" elementFormDefault="qualified" attributeFormDefault="qualified" blockDefault="#all" xmlns="http://schemas.microsoft.com/office/word/2015/wordml/symex" targetNamespace="http://schemas.microsoft.com/office/word/2015/wordml/symex">
<xsd:import id="w12" namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" schemaLocation="../ISO-IEC29500-4_2016/wml.xsd"/>
<xsd:complexType name="CT_SymEx">
<xsd:attribute name="font" type="w12:ST_String"/>
<xsd:attribute name="char" type="w12:ST_LongHexNumber"/>
</xsd:complexType>
<xsd:element name="symEx" type="CT_SymEx"/>
</xsd:schema>
-159
View File
@@ -1,159 +0,0 @@
#!/usr/bin/env python3
"""
Tool to pack a directory into a .docx, .pptx, or .xlsx file with XML formatting undone.
Example usage:
python pack.py <input_directory> <office_file> [--force]
"""
import argparse
import shutil
import subprocess
import sys
import tempfile
import defusedxml.minidom
import zipfile
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description="Pack a directory into an Office file")
parser.add_argument("input_directory", help="Unpacked Office document directory")
parser.add_argument("output_file", help="Output Office file (.docx/.pptx/.xlsx)")
parser.add_argument("--force", action="store_true", help="Skip validation")
args = parser.parse_args()
try:
success = pack_document(
args.input_directory, args.output_file, validate=not args.force
)
# Show warning if validation was skipped
if args.force:
print("Warning: Skipped validation, file may be corrupt", file=sys.stderr)
# Exit with error if validation failed
elif not success:
print("Contents would produce a corrupt file.", file=sys.stderr)
print("Please validate XML before repacking.", file=sys.stderr)
print("Use --force to skip validation and pack anyway.", file=sys.stderr)
sys.exit(1)
except ValueError as e:
sys.exit(f"Error: {e}")
def pack_document(input_dir, output_file, validate=False):
"""Pack a directory into an Office file (.docx/.pptx/.xlsx).
Args:
input_dir: Path to unpacked Office document directory
output_file: Path to output Office file
validate: If True, validates with soffice (default: False)
Returns:
bool: True if successful, False if validation failed
"""
input_dir = Path(input_dir)
output_file = Path(output_file)
if not input_dir.is_dir():
raise ValueError(f"{input_dir} is not a directory")
if output_file.suffix.lower() not in {".docx", ".pptx", ".xlsx"}:
raise ValueError(f"{output_file} must be a .docx, .pptx, or .xlsx file")
# Work in temporary directory to avoid modifying original
with tempfile.TemporaryDirectory() as temp_dir:
temp_content_dir = Path(temp_dir) / "content"
shutil.copytree(input_dir, temp_content_dir)
# Process XML files to remove pretty-printing whitespace
for pattern in ["*.xml", "*.rels"]:
for xml_file in temp_content_dir.rglob(pattern):
condense_xml(xml_file)
# Create final Office file as zip archive
output_file.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(output_file, "w", zipfile.ZIP_DEFLATED) as zf:
for f in temp_content_dir.rglob("*"):
if f.is_file():
zf.write(f, f.relative_to(temp_content_dir))
# Validate if requested
if validate:
if not validate_document(output_file):
output_file.unlink() # Delete the corrupt file
return False
return True
def validate_document(doc_path):
"""Validate document by converting to HTML with soffice."""
# Determine the correct filter based on file extension
match doc_path.suffix.lower():
case ".docx":
filter_name = "html:HTML"
case ".pptx":
filter_name = "html:impress_html_Export"
case ".xlsx":
filter_name = "html:HTML (StarCalc)"
with tempfile.TemporaryDirectory() as temp_dir:
try:
result = subprocess.run(
[
"soffice",
"--headless",
"--convert-to",
filter_name,
"--outdir",
temp_dir,
str(doc_path),
],
capture_output=True,
timeout=10,
text=True,
)
if not (Path(temp_dir) / f"{doc_path.stem}.html").exists():
error_msg = result.stderr.strip() or "Document validation failed"
print(f"Validation error: {error_msg}", file=sys.stderr)
return False
return True
except FileNotFoundError:
print("Warning: soffice not found. Skipping validation.", file=sys.stderr)
return True
except subprocess.TimeoutExpired:
print("Validation error: Timeout during conversion", file=sys.stderr)
return False
except Exception as e:
print(f"Validation error: {e}", file=sys.stderr)
return False
def condense_xml(xml_file):
"""Strip unnecessary whitespace and remove comments."""
with open(xml_file, "r", encoding="utf-8") as f:
dom = defusedxml.minidom.parse(f)
# Process each element to remove whitespace and comments
for element in dom.getElementsByTagName("*"):
# Skip w:t elements and their processing
if element.tagName.endswith(":t"):
continue
# Remove whitespace-only text nodes and comment nodes
for child in list(element.childNodes):
if (
child.nodeType == child.TEXT_NODE
and child.nodeValue
and child.nodeValue.strip() == ""
) or child.nodeType == child.COMMENT_NODE:
element.removeChild(child)
# Write back the condensed XML
with open(xml_file, "wb") as f:
f.write(dom.toxml(encoding="UTF-8"))
if __name__ == "__main__":
main()
-29
View File
@@ -1,29 +0,0 @@
#!/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 <office_file> <output_dir>"
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}")
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env python3
"""
Command line tool to validate Office document XML files against XSD schemas and tracked changes.
Usage:
python validate.py <dir> --original <original_file>
"""
import argparse
import sys
from pathlib import Path
from validation import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator
def main():
parser = argparse.ArgumentParser(description="Validate Office document XML files")
parser.add_argument(
"unpacked_dir",
help="Path to unpacked Office document directory",
)
parser.add_argument(
"--original",
required=True,
help="Path to original file (.docx/.pptx/.xlsx)",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Enable verbose output",
)
args = parser.parse_args()
# Validate paths
unpacked_dir = Path(args.unpacked_dir)
original_file = Path(args.original)
file_extension = original_file.suffix.lower()
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()
@@ -1,15 +0,0 @@
"""
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",
]
-951
View File
@@ -1,951 +0,0 @@
"""
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: <Default Extension="{extension}" ContentType="{media_extensions[extension]}"/>'
)
except Exception as e:
errors.append(f" Error parsing [Content_Types].xml: {e}")
if errors:
print(f"FAILED - Found {len(errors)} content type declaration errors:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print(
"PASSED - All content files are properly declared in [Content_Types].xml"
)
return True
def validate_file_against_xsd(self, xml_file, verbose=False):
"""Validate a single XML file against XSD schema, comparing with original.
Args:
xml_file: Path to XML file to validate
verbose: Enable verbose output
Returns:
tuple: (is_valid, new_errors_set) where is_valid is True/False/None (skipped)
"""
# Resolve both paths to handle symlinks
xml_file = Path(xml_file).resolve()
unpacked_dir = self.unpacked_dir.resolve()
# Validate current file
is_valid, current_errors = self._validate_single_file_xsd(
xml_file, unpacked_dir
)
if is_valid is None:
return None, set() # Skipped
elif is_valid:
return True, set() # Valid, no errors
# Get errors from original file for this specific file
original_errors = self._get_original_file_errors(xml_file)
# Compare with original (both are guaranteed to be sets here)
assert current_errors is not None
new_errors = current_errors - original_errors
if new_errors:
if verbose:
relative_path = xml_file.relative_to(unpacked_dir)
print(f"FAILED - {relative_path}: {len(new_errors)} new error(s)")
for error in list(new_errors)[:3]:
truncated = error[:250] + "..." if len(error) > 250 else error
print(f" - {truncated}")
return False, new_errors
else:
# All errors existed in original
if verbose:
print(
f"PASSED - No new errors (original had {len(current_errors)} errors)"
)
return True, set()
def validate_against_xsd(self):
"""Validate XML files against XSD schemas, showing only new errors compared to original."""
new_errors = []
original_error_count = 0
valid_count = 0
skipped_count = 0
for xml_file in self.xml_files:
relative_path = str(xml_file.relative_to(self.unpacked_dir))
is_valid, new_file_errors = self.validate_file_against_xsd(
xml_file, verbose=False
)
if is_valid is None:
skipped_count += 1
continue
elif is_valid and not new_file_errors:
valid_count += 1
continue
elif is_valid:
# Had errors but all existed in original
original_error_count += 1
valid_count += 1
continue
# Has new errors
new_errors.append(f" {relative_path}: {len(new_file_errors)} new error(s)")
for error in list(new_file_errors)[:3]: # Show first 3 errors
new_errors.append(
f" - {error[:250]}..." if len(error) > 250 else f" - {error}"
)
# Print summary
if self.verbose:
print(f"Validated {len(self.xml_files)} files:")
print(f" - Valid: {valid_count}")
print(f" - Skipped (no schema): {skipped_count}")
if original_error_count:
print(f" - With original errors (ignored): {original_error_count}")
print(
f" - With NEW errors: {len(new_errors) > 0 and len([e for e in new_errors if not e.startswith(' ')]) or 0}"
)
if new_errors:
print("\nFAILED - Found NEW validation errors:")
for error in new_errors:
print(error)
return False
else:
if self.verbose:
print("\nPASSED - No new XSD validation errors introduced")
return True
def _get_schema_path(self, xml_file):
"""Determine the appropriate schema path for an XML file."""
# Check exact filename match
if xml_file.name in self.SCHEMA_MAPPINGS:
return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.name]
# Check .rels files
if xml_file.suffix == ".rels":
return self.schemas_dir / self.SCHEMA_MAPPINGS[".rels"]
# Check chart files
if "charts/" in str(xml_file) and xml_file.name.startswith("chart"):
return self.schemas_dir / self.SCHEMA_MAPPINGS["chart"]
# Check theme files
if "theme/" in str(xml_file) and xml_file.name.startswith("theme"):
return self.schemas_dir / self.SCHEMA_MAPPINGS["theme"]
# Check if file is in a main content folder and use appropriate schema
if xml_file.parent.name in self.MAIN_CONTENT_FOLDERS:
return self.schemas_dir / self.SCHEMA_MAPPINGS[xml_file.parent.name]
return None
def _clean_ignorable_namespaces(self, xml_doc):
"""Remove attributes and elements not in allowed namespaces."""
# Create a clean copy
xml_string = lxml.etree.tostring(xml_doc, encoding="unicode")
xml_copy = lxml.etree.fromstring(xml_string)
# Remove attributes not in allowed namespaces
for elem in xml_copy.iter():
attrs_to_remove = []
for attr in elem.attrib:
# Check if attribute is from a namespace other than allowed ones
if "{" in attr:
ns = attr.split("}")[0][1:]
if ns not in self.OOXML_NAMESPACES:
attrs_to_remove.append(attr)
# Remove collected attributes
for attr in attrs_to_remove:
del elem.attrib[attr]
# Remove elements not in allowed namespaces
self._remove_ignorable_elements(xml_copy)
return lxml.etree.ElementTree(xml_copy)
def _remove_ignorable_elements(self, root):
"""Recursively remove all elements not in allowed namespaces."""
elements_to_remove = []
# Find elements to remove
for elem in list(root):
# Skip non-element nodes (comments, processing instructions, etc.)
if not hasattr(elem, "tag") or callable(elem.tag):
continue
tag_str = str(elem.tag)
if tag_str.startswith("{"):
ns = tag_str.split("}")[0][1:]
if ns not in self.OOXML_NAMESPACES:
elements_to_remove.append(elem)
continue
# Recursively clean child elements
self._remove_ignorable_elements(elem)
# Remove collected elements
for elem in elements_to_remove:
root.remove(elem)
def _preprocess_for_mc_ignorable(self, xml_doc):
"""Preprocess XML to handle mc:Ignorable attribute properly."""
# Remove mc:Ignorable attributes before validation
root = xml_doc.getroot()
# Remove mc:Ignorable attribute from root
if f"{{{self.MC_NAMESPACE}}}Ignorable" in root.attrib:
del root.attrib[f"{{{self.MC_NAMESPACE}}}Ignorable"]
return xml_doc
def _validate_single_file_xsd(self, xml_file, base_path):
"""Validate a single XML file against XSD schema. Returns (is_valid, errors_set)."""
schema_path = self._get_schema_path(xml_file)
if not schema_path:
return None, None # Skip file
try:
# Load schema
with open(schema_path, "rb") as xsd_file:
parser = lxml.etree.XMLParser()
xsd_doc = lxml.etree.parse(
xsd_file, parser=parser, base_url=str(schema_path)
)
schema = lxml.etree.XMLSchema(xsd_doc)
# Load and preprocess XML
with open(xml_file, "r") as f:
xml_doc = lxml.etree.parse(f)
xml_doc, _ = self._remove_template_tags_from_text_nodes(xml_doc)
xml_doc = self._preprocess_for_mc_ignorable(xml_doc)
# Clean ignorable namespaces if needed
relative_path = xml_file.relative_to(base_path)
if (
relative_path.parts
and relative_path.parts[0] in self.MAIN_CONTENT_FOLDERS
):
xml_doc = self._clean_ignorable_namespaces(xml_doc)
# Validate
if schema.validate(xml_doc):
return True, set()
else:
errors = set()
for error in schema.error_log:
# Store normalized error message (without line numbers for comparison)
errors.add(error.message)
return False, errors
except Exception as e:
return False, {str(e)}
def _get_original_file_errors(self, xml_file):
"""Get XSD validation errors from a single file in the original document.
Args:
xml_file: Path to the XML file in unpacked_dir to check
Returns:
set: Set of error messages from the original file
"""
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.")
-274
View File
@@ -1,274 +0,0 @@
"""
Validator for Word document XML files against XSD schemas.
"""
import re
import tempfile
import zipfile
import lxml.etree
from .base import BaseSchemaValidator
class DOCXSchemaValidator(BaseSchemaValidator):
"""Validator for Word document XML files against XSD schemas."""
# Word-specific namespace
WORD_2006_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
# Word-specific element to relationship type mappings
# Start with empty mapping - add specific cases as we discover them
ELEMENT_RELATIONSHIP_TYPES = {}
def validate(self):
"""Run all validation checks and return True if all pass."""
# Test 0: XML well-formedness
if not self.validate_xml():
return False
# Test 1: Namespace declarations
all_valid = True
if not self.validate_namespaces():
all_valid = False
# Test 2: Unique IDs
if not self.validate_unique_ids():
all_valid = False
# Test 3: Relationship and file reference validation
if not self.validate_file_references():
all_valid = False
# Test 4: Content type declarations
if not self.validate_content_types():
all_valid = False
# Test 5: XSD schema validation
if not self.validate_against_xsd():
all_valid = False
# Test 6: Whitespace preservation
if not self.validate_whitespace_preservation():
all_valid = False
# Test 7: Deletion validation
if not self.validate_deletions():
all_valid = False
# Test 8: Insertion validation
if not self.validate_insertions():
all_valid = False
# Test 9: Relationship ID reference validation
if not self.validate_all_relationship_ids():
all_valid = False
# Count and compare paragraphs
self.compare_paragraph_counts()
return all_valid
def validate_whitespace_preservation(self):
"""
Validate that w:t elements with whitespace have xml:space='preserve'.
"""
errors = []
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Find all w:t elements
for elem in root.iter(f"{{{self.WORD_2006_NAMESPACE}}}t"):
if elem.text:
text = elem.text
# Check if text starts or ends with whitespace
if re.match(r"^\s.*", text) or re.match(r".*\s$", text):
# Check if xml:space="preserve" attribute exists
xml_space_attr = f"{{{self.XML_NAMESPACE}}}space"
if (
xml_space_attr not in elem.attrib
or elem.attrib[xml_space_attr] != "preserve"
):
# Show a preview of the text
text_preview = (
repr(text)[:50] + "..."
if len(repr(text)) > 50
else repr(text)
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: w:t element with whitespace missing xml:space='preserve': {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} whitespace preservation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - All whitespace is properly preserved")
return True
def validate_deletions(self):
"""
Validate that w:t elements are not within w:del elements.
For some reason, XSD validation does not catch this, so we do it manually.
"""
errors = []
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Find all w:t elements that are descendants of w:del elements
namespaces = {"w": self.WORD_2006_NAMESPACE}
xpath_expression = ".//w:del//w:t"
problematic_t_elements = root.xpath(
xpath_expression, namespaces=namespaces
)
for t_elem in problematic_t_elements:
if t_elem.text:
# Show a preview of the text
text_preview = (
repr(t_elem.text)[:50] + "..."
if len(repr(t_elem.text)) > 50
else repr(t_elem.text)
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {t_elem.sourceline}: <w:t> found within <w:del>: {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} deletion validation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - No w:t elements found within w:del elements")
return True
def count_paragraphs_in_unpacked(self):
"""Count the number of paragraphs in the unpacked document."""
count = 0
for xml_file in self.xml_files:
# Only check document.xml files
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
# Count all w:p elements
paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p")
count = len(paragraphs)
except Exception as e:
print(f"Error counting paragraphs in unpacked document: {e}")
return count
def count_paragraphs_in_original(self):
"""Count the number of paragraphs in the original docx file."""
count = 0
try:
# Create temporary directory to unpack original
with tempfile.TemporaryDirectory() as temp_dir:
# Unpack original docx
with zipfile.ZipFile(self.original_file, "r") as zip_ref:
zip_ref.extractall(temp_dir)
# Parse document.xml
doc_xml_path = temp_dir + "/word/document.xml"
root = lxml.etree.parse(doc_xml_path).getroot()
# Count all w:p elements
paragraphs = root.findall(f".//{{{self.WORD_2006_NAMESPACE}}}p")
count = len(paragraphs)
except Exception as e:
print(f"Error counting paragraphs in original document: {e}")
return count
def validate_insertions(self):
"""
Validate that w:delText elements are not within w:ins elements.
w:delText is only allowed in w:ins if nested within a w:del.
"""
errors = []
for xml_file in self.xml_files:
if xml_file.name != "document.xml":
continue
try:
root = lxml.etree.parse(str(xml_file)).getroot()
namespaces = {"w": self.WORD_2006_NAMESPACE}
# Find w:delText in w:ins that are NOT within w:del
invalid_elements = root.xpath(
".//w:ins//w:delText[not(ancestor::w:del)]",
namespaces=namespaces
)
for elem in invalid_elements:
text_preview = (
repr(elem.text or "")[:50] + "..."
if len(repr(elem.text or "")) > 50
else repr(elem.text or "")
)
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: "
f"Line {elem.sourceline}: <w:delText> within <w:ins>: {text_preview}"
)
except (lxml.etree.XMLSyntaxError, Exception) as e:
errors.append(
f" {xml_file.relative_to(self.unpacked_dir)}: Error: {e}"
)
if errors:
print(f"FAILED - Found {len(errors)} insertion validation violations:")
for error in errors:
print(error)
return False
else:
if self.verbose:
print("PASSED - No w:delText elements within w:ins elements")
return True
def compare_paragraph_counts(self):
"""Compare paragraph counts between original and new document."""
original_count = self.count_paragraphs_in_original()
new_count = self.count_paragraphs_in_unpacked()
diff = new_count - original_count
diff_str = f"+{diff}" if diff > 0 else str(diff)
print(f"\nParagraphs: {original_count}{new_count} ({diff_str})")
if __name__ == "__main__":
raise RuntimeError("This module should not be run directly.")
-315
View File
@@ -1,315 +0,0 @@
"""
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.")
@@ -1,279 +0,0 @@
"""
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 <w:ins> or <w:del> tags",
" 2. Made edits without proper tracked changes",
" 3. Didn't nest <w:del> inside <w:ins> when deleting another's insertion",
"",
"For pre-redlined documents, use correct patterns:",
" - To reject another's INSERTION: Nest <w:del> inside their <w:ins>",
" - To restore another's DELETION: Add new <w:ins> AFTER their <w:del>",
"",
]
# Show git word diff
git_diff = self._get_git_word_diff(original_text, modified_text)
if git_diff:
error_parts.extend(["Differences:", "============", git_diff])
else:
error_parts.append("Unable to generate word diff (git not available)")
return "\n".join(error_parts)
def _get_git_word_diff(self, original_text, modified_text):
"""Generate word diff using git with character-level precision."""
try:
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Create two files
original_file = temp_path / "original.txt"
modified_file = temp_path / "modified.txt"
original_file.write_text(original_text, encoding="utf-8")
modified_file.write_text(modified_text, encoding="utf-8")
# Try character-level diff first for precise differences
result = subprocess.run(
[
"git",
"diff",
"--word-diff=plain",
"--word-diff-regex=.", # Character-by-character diff
"-U0", # Zero lines of context - show only changed lines
"--no-index",
str(original_file),
str(modified_file),
],
capture_output=True,
text=True,
)
if result.stdout.strip():
# Clean up the output - remove git diff header lines
lines = result.stdout.split("\n")
# Skip the header lines (diff --git, index, +++, ---, @@)
content_lines = []
in_content = False
for line in lines:
if line.startswith("@@"):
in_content = True
continue
if in_content and line.strip():
content_lines.append(line)
if content_lines:
return "\n".join(content_lines)
# Fallback to word-level diff if character-level is too verbose
result = subprocess.run(
[
"git",
"diff",
"--word-diff=plain",
"-U0", # Zero lines of context
"--no-index",
str(original_file),
str(modified_file),
],
capture_output=True,
text=True,
)
if result.stdout.strip():
lines = result.stdout.split("\n")
content_lines = []
in_content = False
for line in lines:
if line.startswith("@@"):
in_content = True
continue
if in_content and line.strip():
content_lines.append(line)
return "\n".join(content_lines)
except (subprocess.CalledProcessError, FileNotFoundError, Exception):
# Git not available or other error, return None to use fallback
pass
return None
def _remove_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.")
-1
View File
@@ -1 +0,0 @@
# Make scripts directory a package for relative imports in tests
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:comments xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16sdtfl="http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16sdtfl w16du wp14">
</w:comments>
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w15:commentsEx xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16sdtfl="http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16sdtfl w16du wp14">
</w15:commentsEx>
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w16cex:commentsExtensible xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16sdtfl="http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" xmlns:cr="http://schemas.microsoft.com/office/comments/2020/reactions" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16sdtfl cr w16du wp14">
</w16cex:commentsExtensible>
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w16cid:commentsIds xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16sdtfl="http://schemas.microsoft.com/office/word/2024/wordml/sdtformatlock" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16sdtfl w16du wp14">
</w16cid:commentsIds>
-3
View File
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w15:people xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml">
</w15:people>
-374
View File
@@ -1,374 +0,0 @@
#!/usr/bin/env python3
"""
Utilities for editing OOXML documents.
This module provides XMLEditor, a tool for manipulating XML files with support for
line-number-based node finding and DOM manipulation. Each element is automatically
annotated with its original line and column position during parsing.
Example usage:
editor = XMLEditor("document.xml")
# Find node by line number or range
elem = editor.get_node(tag="w:r", line_number=519)
elem = editor.get_node(tag="w:p", line_number=range(100, 200))
# Find node by text content
elem = editor.get_node(tag="w:p", contains="specific text")
# Find node by attributes
elem = editor.get_node(tag="w:r", attrs={"w:id": "target"})
# Combine filters
elem = editor.get_node(tag="w:p", line_number=range(1, 50), contains="text")
# Replace, insert, or manipulate
new_elem = editor.replace_node(elem, "<w:r><w:t>new text</w:t></w:r>")
editor.insert_after(new_elem, "<w:r><w:t>more</w:t></w:r>")
# Save changes
editor.save()
"""
import html
from pathlib import Path
from typing import Optional, Union
import defusedxml.minidom
import defusedxml.sax
class XMLEditor:
"""
Editor for manipulating OOXML XML files with line-number-based node finding.
This class parses XML files and tracks the original line and column position
of each element. This enables finding nodes by their line number in the original
file, which is useful when working with Read tool output.
Attributes:
xml_path: Path to the XML file being edited
encoding: Detected encoding of the XML file ('ascii' or 'utf-8')
dom: Parsed DOM tree with parse_position attributes on elements
"""
def __init__(self, xml_path):
"""
Initialize with path to XML file and parse with line number tracking.
Args:
xml_path: Path to XML file to edit (str or Path)
Raises:
ValueError: If the XML file does not exist
"""
self.xml_path = Path(xml_path)
if not self.xml_path.exists():
raise ValueError(f"XML file not found: {xml_path}")
with open(self.xml_path, "rb") as f:
header = f.read(200).decode("utf-8", errors="ignore")
self.encoding = "ascii" if 'encoding="ascii"' in header else "utf-8"
parser = _create_line_tracking_parser()
self.dom = defusedxml.minidom.parse(str(self.xml_path), parser)
def get_node(
self,
tag: str,
attrs: Optional[dict[str, str]] = None,
line_number: Optional[Union[int, range]] = None,
contains: Optional[str] = None,
):
"""
Get a DOM element by tag and identifier.
Finds an element by either its line number in the original file or by
matching attribute values. Exactly one match must be found.
Args:
tag: The XML tag name (e.g., "w:del", "w:ins", "w:r")
attrs: Dictionary of attribute name-value pairs to match (e.g., {"w:id": "1"})
line_number: Line number (int) or line range (range) in original XML file (1-indexed)
contains: Text string that must appear in any text node within the element.
Supports both entity notation (&#8220;) and Unicode characters (\u201c).
Returns:
defusedxml.minidom.Element: The matching DOM element
Raises:
ValueError: If node not found or multiple matches found
Example:
elem = editor.get_node(tag="w:r", line_number=519)
elem = editor.get_node(tag="w:r", line_number=range(100, 200))
elem = editor.get_node(tag="w:del", attrs={"w:id": "1"})
elem = editor.get_node(tag="w:p", attrs={"w14:paraId": "12345678"})
elem = editor.get_node(tag="w:commentRangeStart", attrs={"w:id": "0"})
elem = editor.get_node(tag="w:p", contains="specific text")
elem = editor.get_node(tag="w:t", contains="&#8220;Agreement") # Entity notation
elem = editor.get_node(tag="w:t", contains="\u201cAgreement") # Unicode character
"""
matches = []
for elem in self.dom.getElementsByTagName(tag):
# Check line_number filter
if line_number is not None:
parse_pos = getattr(elem, "parse_position", (None,))
elem_line = parse_pos[0]
# Handle both single line number and range
if isinstance(line_number, range):
if elem_line not in line_number:
continue
else:
if elem_line != line_number:
continue
# Check attrs filter
if attrs is not None:
if not all(
elem.getAttribute(attr_name) == attr_value
for attr_name, attr_value in attrs.items()
):
continue
# Check contains filter
if contains is not None:
elem_text = self._get_element_text(elem)
# Normalize the search string: convert HTML entities to Unicode characters
# This allows searching for both "&#8220;Rowan" and ""Rowan"
normalized_contains = html.unescape(contains)
if normalized_contains not in elem_text:
continue
# If all applicable filters passed, this is a match
matches.append(elem)
if not matches:
# Build descriptive error message
filters = []
if line_number is not None:
line_str = (
f"lines {line_number.start}-{line_number.stop - 1}"
if isinstance(line_number, range)
else f"line {line_number}"
)
filters.append(f"at {line_str}")
if attrs is not None:
filters.append(f"with attributes {attrs}")
if contains is not None:
filters.append(f"containing '{contains}'")
filter_desc = " ".join(filters) if filters else ""
base_msg = f"Node not found: <{tag}> {filter_desc}".strip()
# Add helpful hint based on filters used
if contains:
hint = "Text may be split across elements or use different wording."
elif line_number:
hint = "Line numbers may have changed if document was modified."
elif attrs:
hint = "Verify attribute values are correct."
else:
hint = "Try adding filters (attrs, line_number, or contains)."
raise ValueError(f"{base_msg}. {hint}")
if len(matches) > 1:
raise ValueError(
f"Multiple nodes found: <{tag}>. "
f"Add more filters (attrs, line_number, or contains) to narrow the search."
)
return matches[0]
def _get_element_text(self, elem):
"""
Recursively extract all text content from an element.
Skips text nodes that contain only whitespace (spaces, tabs, newlines),
which typically represent XML formatting rather than document content.
Args:
elem: defusedxml.minidom.Element to extract text from
Returns:
str: Concatenated text from all non-whitespace text nodes within the element
"""
text_parts = []
for node in elem.childNodes:
if node.nodeType == node.TEXT_NODE:
# Skip whitespace-only text nodes (XML formatting)
if node.data.strip():
text_parts.append(node.data)
elif node.nodeType == node.ELEMENT_NODE:
text_parts.append(self._get_element_text(node))
return "".join(text_parts)
def replace_node(self, elem, new_content):
"""
Replace a DOM element with new XML content.
Args:
elem: defusedxml.minidom.Element to replace
new_content: String containing XML to replace the node with
Returns:
List[defusedxml.minidom.Node]: All inserted nodes
Example:
new_nodes = editor.replace_node(old_elem, "<w:r><w:t>text</w:t></w:r>")
"""
parent = elem.parentNode
nodes = self._parse_fragment(new_content)
for node in nodes:
parent.insertBefore(node, elem)
parent.removeChild(elem)
return nodes
def insert_after(self, elem, xml_content):
"""
Insert XML content after a DOM element.
Args:
elem: defusedxml.minidom.Element to insert after
xml_content: String containing XML to insert
Returns:
List[defusedxml.minidom.Node]: All inserted nodes
Example:
new_nodes = editor.insert_after(elem, "<w:r><w:t>text</w:t></w:r>")
"""
parent = elem.parentNode
next_sibling = elem.nextSibling
nodes = self._parse_fragment(xml_content)
for node in nodes:
if next_sibling:
parent.insertBefore(node, next_sibling)
else:
parent.appendChild(node)
return nodes
def insert_before(self, elem, xml_content):
"""
Insert XML content before a DOM element.
Args:
elem: defusedxml.minidom.Element to insert before
xml_content: String containing XML to insert
Returns:
List[defusedxml.minidom.Node]: All inserted nodes
Example:
new_nodes = editor.insert_before(elem, "<w:r><w:t>text</w:t></w:r>")
"""
parent = elem.parentNode
nodes = self._parse_fragment(xml_content)
for node in nodes:
parent.insertBefore(node, elem)
return nodes
def append_to(self, elem, xml_content):
"""
Append XML content as a child of a DOM element.
Args:
elem: defusedxml.minidom.Element to append to
xml_content: String containing XML to append
Returns:
List[defusedxml.minidom.Node]: All inserted nodes
Example:
new_nodes = editor.append_to(elem, "<w:r><w:t>text</w:t></w:r>")
"""
nodes = self._parse_fragment(xml_content)
for node in nodes:
elem.appendChild(node)
return nodes
def get_next_rid(self):
"""Get the next available rId for relationships files."""
max_id = 0
for rel_elem in self.dom.getElementsByTagName("Relationship"):
rel_id = rel_elem.getAttribute("Id")
if rel_id.startswith("rId"):
try:
max_id = max(max_id, int(rel_id[3:]))
except ValueError:
pass
return f"rId{max_id + 1}"
def save(self):
"""
Save the edited XML back to the file.
Serializes the DOM tree and writes it back to the original file path,
preserving the original encoding (ascii or utf-8).
"""
content = self.dom.toxml(encoding=self.encoding)
self.xml_path.write_bytes(content)
def _parse_fragment(self, xml_content):
"""
Parse XML fragment and return list of imported nodes.
Args:
xml_content: String containing XML fragment
Returns:
List of defusedxml.minidom.Node objects imported into this document
Raises:
AssertionError: If fragment contains no element nodes
"""
# Extract namespace declarations from the root document element
root_elem = self.dom.documentElement
namespaces = []
if root_elem and root_elem.attributes:
for i in range(root_elem.attributes.length):
attr = root_elem.attributes.item(i)
if attr.name.startswith("xmlns"): # type: ignore
namespaces.append(f'{attr.name}="{attr.value}"') # type: ignore
ns_decl = " ".join(namespaces)
wrapper = f"<root {ns_decl}>{xml_content}</root>"
fragment_doc = defusedxml.minidom.parseString(wrapper)
nodes = [
self.dom.importNode(child, deep=True)
for child in fragment_doc.documentElement.childNodes # type: ignore
]
elements = [n for n in nodes if n.nodeType == n.ELEMENT_NODE]
assert elements, "Fragment must contain at least one element"
return nodes
def _create_line_tracking_parser():
"""
Create a SAX parser that tracks line and column numbers for each element.
Monkey patches the SAX content handler to store the current line and column
position from the underlying expat parser onto each element as a parse_position
attribute (line, column) tuple.
Returns:
defusedxml.sax.xmlreader.XMLReader: Configured SAX parser
"""
def set_content_handler(dom_handler):
def startElementNS(name, tagName, attrs):
orig_start_cb(name, tagName, attrs)
cur_elem = dom_handler.elementStack[-1]
cur_elem.parse_position = (
parser._parser.CurrentLineNumber, # type: ignore
parser._parser.CurrentColumnNumber, # type: ignore
)
orig_start_cb = dom_handler.startElementNS
dom_handler.startElementNS = startElementNS
orig_set_content_handler(dom_handler)
parser = defusedxml.sax.make_parser()
orig_set_content_handler = parser.setContentHandler
parser.setContentHandler = set_content_handler # type: ignore
return parser
-739
View File
@@ -1,739 +0,0 @@
# GhostEditor / md2gost — полное описание проекта
Версия пакета: **0.1.0**. Python **≥ 3.10**.
Репозиторий: конвертер учебных отчётов **Markdown → DOCX** по методичке РТУ МИРЭА (ГОСТ 7.32-2017) и профилям **ПИС / АПИД**. Рядом — два дополнительных пайплайна: **FODT** (LibreOffice) и **LaTeX → PDF**.
Этот файл — карта всего репозитория: что уже работает, как устроен код, какие функции есть в CLI/GUI и какие модули за что отвечают. Пользовательская документация по разделам лежит в [`docs/`](docs/).
---
## 1. Зачем проект существует
Студент пишет отчёт в расширенном Markdown (диалект md2gost). Конвертер сам:
- оформляет DOCX стилями Times New Roman, полями 30/10/20/20 мм, интервалом 1.5;
- нумерует рисунки, таблицы, листинги, формулы;
- собирает содержание и список источников;
- рисует UML / C4 / Mermaid;
- проверяет структуру по ТЗ (`--check`);
- при необходимости режет длинные таблицы и листинги через Microsoft Word и пишет «Продолжение…».
Исходный форк: [benzlokzik/md2gost](https://github.com/benzlokzik/md2gost). Здесь — своя линия: профили МИРЭА/ПИС/АПИД, GUI, схемы, стили JSON, Word COM, FODT, LaTeX.
---
## 2. Три продукта в одном репозитории
| Пакет | Entry point | Результат | Когда |
|--------|-------------|-----------|--------|
| **md2gost** | `python -m md2gost` / `md2gost-gui` | `.docx` | основной путь, Word |
| **md2fodt** | `python -m md2fodt` | `.fodt` | LibreOffice, без Word |
| **md2latex** | `python -m md2latex` | каталог XeLaTeX (+ `--pdf`) | PDF через шаблон МИРЭА |
| **word2md** | `python -m word2md` / `md2gost файл.docx` | `.md` | импорт DOCX → диалект md2gost |
Общий диалект разметки: спецразделы `# *ВВЕДЕНИЕ`, метки `%id`, ссылки `@Рисунок:id`, таблицы с `^`/`>`, формулы `$$`, библиография `[n]: …`.
Полнота реализации **не одинаковая**:
- **md2gost** — полный конвейер (стили, профили, диаграммы, checker, GUI, Word COM).
- **md2fodt** — v1: текст, заголовки, списки, таблицы с merge, картинки, листинги, простые ссылки, библиография. Нет PlantUML, нет «Продолжение таблицы», нет полного паритета PIS/АПИД.
- **md2latex** — тот же диалект → `content.tex` + копия `latex/mirea/`. Таблицы идут в `longtable` с настоящим «Продолжение таблицы N» (это умеет LaTeX, не Word).
- **word2md** — эвристический DOCX → диалект md2gost (стили Caption/Heading, подписи, таблицы, Code, формулы OMML). Не восстанавливает UML/Mermaid и исходные `%id`.
---
## 3. Как запустить
```bash
pip install -e .
python -m md2gost # GUI
python -m md2gost report.md -o report.docx --type coursework --check
python -m word2md report.docx -o report.md
python -m md2fodt report.md -o report.fodt
python -m md2latex report.md -o report_latex --pdf
```
Windows exe: `build-exe.bat``dist\md2gost.exe` (двойной клик — GUI; из консоли работает как CLI; перед сборкой тянет plantuml.jar и portable Graphviz).
Быстрая сборка: `build-exe-fast.bat` + `md2gost.fast.spec`.
Для режима продолжения таблиц/листингов `word` (по умолчанию): Windows + Microsoft Word + `pip install pywin32` (опциональная группа `[word]`).
---
## 4. Архитектура md2gost (главный конвейер)
Один движок на CLI и GUI. GUI только собирает `ConvertRequest` и зовёт `convert()`.
```
.md
├─ checker.check_markdown() # если --check / --check-only
├─ profiles.preprocess_markdown() # «ёлочки», тире; не трогает UML/Mermaid
├─ Parser (marko + extended_markdown)
│ └─ RenderableFactory → список Renderable
├─ biblio_processor.fold_bibliography()
├─ Heading / ToC / Table / Listing: режимы нумерации и continuation
├─ label_pass.assign_numbers() + resolve @Тип:id
├─ Renderer.process() # LayoutTracker, секции, альбом, колонтитулы
├─ TocProcessor.process() # native TOC field или ручная сборка
├─ [опционально] docxcompose: титул + задание + тело
├─ document.save()
├─ [если word] word_fix.fix_continuations() # COM: реальные разрывы страниц
└─ [если --check-pages] page_fill_check # эвристика полупустых страниц
```
Ключевые типы:
- `ConvertRequest` / `ConvertResult` — контракт CLI↔GUI (`md2gost/pipeline.py`).
- `DocProfile` — правила типа работы (`md2gost/profiles.py`).
- `StyleConfig` — поля страницы + стили абзацев (`md2gost/style_config.py`).
- `Renderable` — элемент, который умеет себя нарисовать в DOCX с учётом высоты страницы.
---
## 5. Что уже умеет пользователь (функции продукта)
### 5.1. Типы документов (`--type`)
| Тип | Стили | Нумерация объектов | Источники | Структура |
|-----|--------|-------------------|-----------|-----------|
| `practice` | mirea | по разделам `1.1`, `2.1` | 5–7, ≤5 лет | Введение, разделы, заключение, список, приложения |
| `coursework` | mirea | то же | 57, ≤5 лет | то же |
| `vkr` | mirea | то же | ≥10 **в каждом** разделе списка, ссылки `[1.5]` | + приложение «Графический материал» |
| `PIS_custom` | pis_custom | сквозная `1, 2, 3` | не обязательны | H1 = «Практическая работа №N. …»; H1 по центру ПРОПИСНЫМИ; H2 с абзацным отступом |
| `APID_coursework` | mirea | по разделам | 7–20, ≤5 лет | обязательные главы «Теоретические…» / «Прикладные…» и пункты 2.1–2.4 |
Реализация: `PROFILES` и `get_profile()` в `profiles.py`. Стили пресетов: `preset_mirea()`, `preset_pis_custom()`.
### 5.2. CLI (все флаги)
Точка входа: `md2gost/__main__.py``build_parser()`, `request_from_args()`, `main()`.
| Флаг | По умолчанию | Что делает |
|------|----------------|------------|
| `filename` | нет → GUI | `.md` или `.docx` с `--check-pages` |
| `--gui` | | открыть окно (можно сразу передать `.md`) |
| `-o` / `--output` | рядом с md, то же имя | выходной DOCX |
| `-t` / `--template` | `md2gost/Template.docx` | шаблон Word |
| `--type` | `practice` | профиль документа |
| `--heading-numbering` | `manual` | `manual` — цифры из md, автонумерация Word выкл.; `auto` — нумерует Word, цифры в начале заголовка снимаются |
| `--toc` | `native` | `native` — поле Word `TOC`; `manual` — сборка по LayoutTracker |
| `--table-continuation` | `word` | `word` / `off` / `soft` / `legacy` / `caption` |
| `--listing-continuation` | `word` | то же для листингов |
| `--table-repeat-header` | выкл. | шапка на фрагментах после word-split |
| `--emdash-to-hyphen` | выкл. | «—» → «-» |
| `--hr-pagebreak` | выкл. | `---` / `***` / `___` → разрыв страницы |
| `--title` / `--assignment` | | DOCX титула и бланка задания (склейка через docxcompose) |
| `--auto-title` / `--no-auto-title` | | автотитул из yaml/` ```title ` (по умолчанию выкл.) |
| `--student` / `--group` | | ФИО и группа для автотитула (иначе `md2gost.user.json`) |
| `--doc-author-from` / `--doc-author` | `os` / профиль | автор в свойствах DOCX: `os` (имя ОС), `student`, `custom` |
| `--doc-title` / `--doc-subject` / `--doc-keywords` / `--doc-comments` / `--doc-category` / `--doc-last-modified-by` | см. профиль | остальные поля File → сведения; пустые comments — без штампа md2gost |
| `--check` / `--check-only` / `--strict` | | проверка ТЗ; `--strict` → код выхода 1 при ошибках |
| `--check-pages` | | полупустые страницы через Word COM (эвристика, не влияет на `--strict`) |
| `--syntax-highlighting` | | Pygments в листингах |
| `--plantuml-jar` / `--kroki-url` | | локальный рендер диаграмм |
| `--diagram-fallback` | `remote` | `remote` / `local` / `off` |
| `--diagram-format` | `png` | `png` или `svg` (svgBlip + PNG-запасной) |
| `--diagram-scale` | `2.0` | качество PNG PlantUML (размер на странице как при 1) |
| `--schemes` | авто | путь к `md2gost.schemes.json` |
| `--styles` | авто | оверлей `md2gost.styles.json` |
| `--debug` | | отладочная сетка в документе + открыть файл |
Занятый выходной файл: `timestamped_output_path()` пишет `имя_ГГГГ-ММ-ДД-ЧЧ-ММ.docx`.
Windowed exe: `_argv_needs_console()` + `_enable_windows_console()` — консоль появляется только для CLI/`--help`, не для GUI.
### 5.3. GUI (Tkinter)
Модуль `md2gost/gui.py`, класс `Md2GostApp`. Entry: `md2gost-gui` / `python -m md2gost` без файла / `--gui`.
Уже есть:
- зона Drop: перетаскивание `.md` (tkinterdnd2, иначе Win32 `WM_DROPFILES`, иначе клик → диалог);
- основные параметры: тип, нумерация заголовков, TOC, continuation таблиц/листингов, тире, `---` → разрыв, проверки ТЗ, вёрстка, открыть после сборки;
- **Настройки → Файлы**: шаблон, титул, задание, стили JSON, выходной путь;
- **Настройки → Студент…**: ФИО и группа (первый запуск);
- **Настройки → Метаданные…**: свойства DOCX (автор, название, тема, теги, примечание) в `md2gost.user.json`;
- **Настройки → Диаграммы**: jar, Kroki, fallback, формат, масштаб, статус движка, скачать PlantUML, сброс кэша includes;
- **Шаблоны UML**: CRUD схем (`md2gost.schemes.json`) — добавить / дублировать / удалить / сохранить / открыть JSON;
- **Справка**: Инструкция, Документация (вшитые `docs/*.md`), Схемы, Промпт для ИИ (каталог `prompts/` + кнопки схем);
- конвертация в фоне (`threading`), лог в окне, тултипы, меню «Дебаг» на одну следующую сборку;
- если выходной DOCX занят — timestamp-имя, как в CLI.
Конвертация не блокирует окно: `_convert()` → поток → `_on_done()`.
### 5.4. Диалект Markdown
Реализовано в `extended_markdown/` (расширение Marko + GFM) и `RenderableFactory`.
| Элемент | Синтаксис | Поведение |
|---------|-----------|-----------|
| Спецраздел без номера | `# *ВВЕДЕНИЕ` | ПРОПИСНЫЕ, без автономера раздела |
| Содержание | `# *СОДЕРЖАНИЕ` + `[TOC]` | native поле Word или ручная сборка |
| Рисунок-файл | `![…](file.png "%id Подпись")` | нумерация + `@Рисунок:id` |
| Таблица | `%id Подпись` перед таблицей | подпись «Таблица N — …» |
| Merge ячеек | `^` rowspan, `>` colspan | OOXML `vMerge` / `gridSpan`; через разрыв страницы merge не переносится |
| Листинг | `%id` + code fence | Courier New, опционально Pygments |
| Диаграмма | `%id` + ` ```uml ` / `uml-c4` / `mermaid` / `idef0` / `dfd` | Рисунок; флаги `+listing`, `+landscape` |
| Формула | `%eq1` + `$$…$$` + `@Формула:eq1` | номер только если есть ссылка |
| Инлайн-формула | `$…$` | OMML в абзаце |
| Ссылка на объект | `@Рисунок:id`, `@Таблица:id`, `@Листинг:id`, `@Формула:id` | подстановка номера |
| Источник | `[1]` в тексте, `[1]: …` в списке | ВКР: `[1.5]`, цитата `[2.18, c. 21-25]` |
| Разрыв страницы | `---` + `--hr-pagebreak` | иначе HR игнорируется |
| Жирный / курсив / зачёркивание / ссылки / списки | обычный MD | поддерживается |
Автоправки текста (`preprocess_markdown`):
- `"..."` → «…» (эвристика, не внутри `%…`);
- `слово - слово``слово — слово` (если не `--emdash-to-hyphen`);
- внутри оград UML/Mermaid/схем **не** трогает кавычки и тире;
- в списке источников каждый `[n]:` выносится в отдельный абзац (`separate_biblio_lines`).
### 5.5. Схемы и диаграммы
Встроенные id (`md2gost/diagrams/schemes.json`): `c4`, `c4context`, `c4component`, `usecase`.
Слои загрузки (позже побеждает): встроенный шаблон → `md2gost.schemes.json` рядом с приложением (создаётся при первом запуске, не перезаписывается) → рядом с `.md``--schemes`.
Рендер UML:
1. Java + `plantuml.jar` (вшитый / `%LOCALAPPDATA%\md2gost\` / `--plantuml-jar`);
2. локальный Kroki (`KROKI_URL` / `--kroki-url`);
3. `https://kroki.io` при `--diagram-fallback remote`.
Mermaid — локально (браузер / QuickJS) или Kroki. **IDEF0** — оградка ` ```idef0 `, локальный Pillow (рамка NIST). **DFD** — оградка ` ```dfd `, пакет [data-flow-diagram](https://github.com/pbauermeister/dfd) → вшитый/кэш/PATH Graphviz (`scripts/fetch_graphviz.py`, GUI «Скачать Graphviz») или Kroki.
Кэш картинок: `{каталог_md}/.md2gost-cache/`.
Кэш `!include` URL: `md2gost.include-cache.json` + `include-cache/`.
Альбомная страница: флаг `+landscape` у подписи — отдельная секция A4 landscape с вертикальным центрированием, затем снова книжная. Один section break (без пустой книжной страницы перед альбомом).
### 5.6. Кастомные стили JSON
Файл `md2gost.styles.json` (рядом с `.md` и/или `--styles`). Deep-merge поверх пресета типа. Неизвестный ключ или имя стиля — ошибка (`StyleConfigError`).
Можно менять поля `page` (мм) и поля стилей абзацев: шрифт, кегль, жирный/курсив/прописные, выравнивание, отступы, интервал 1.0/1.5, `page_break_before`, `keep_with_next`, `widow_control`.
Не в JSON: табы оглавления (считаются от ширины полосы), отступы списков, цвет (всегда чёрный), формулы из шаблона.
### 5.7. Проверка ТЗ (`--check`)
Модуль `md2gost/checker/__init__.py`. Возвращает `Issue(id, severity, message, line)`.
Уже проверяется:
- обязательные разделы по профилю (СОДЕРЖАНИЕ, ВВЕДЕНИЕ, ЗАКЛЮЧЕНИЕ, список; для ПИС — практические работы; для ВКР — «Графический материал»; для АПИД — 6 обязательных заголовков);
- `[TOC]`;
- спецразделы должны быть `# *…`, лучше ПРОПИСНЫМИ;
- запрет «рис.», «табл.», сносок `[^1]`, графы «№ п/п»;
- ссылки `[n]` во введении/заключении запрещены;
- число и возраст источников; для ВКР — по разделам списка; порядок первого упоминания;
- висячие / неиспользованные метки `%id` / `@Тип:id`;
- запрещённые буквы приложений (Ё З Й О Ч Ь Ы Ъ);
- перечень приложений после `# *ПРИЛОЖЕНИЯ`, если приложений ≥ 2;
- маркеры merge `^`/`>` в шапке и `>` в первом столбце;
- подсказка про «Продолжение…», если continuation = `off`/`soft`.
`--strict` падает только на `severity == "error"`. `--check-pages` — отдельная эвристика, в strict не входит.
### 5.8. Продолжение таблиц и листингов
DOCX сам не умеет писать «Продолжение Таблицы N» только со 2-й страницы.
| Режим | Поведение |
|--------|-----------|
| **`word`** (по умолчанию) | После save Word COM режет по реальной пагинации, вставляет подпись |
| **`off` / `soft`** | Одна таблица/листинг, пагинацию делает Word, без автоподписи |
| **`legacy`** | Резка по оценке высоты LayoutTracker + `page_break_before` (могут быть дыры) |
| **`caption`** | То же + явный PageBreak |
Оценка высоты ≠ вёрстка Word — поэтому `legacy`/`caption` помечены как неточные.
### 5.9. Титул, задание, колонтитулы
`--title` / `--assignment`: пустая оболочка из шаблона + docxcompose (титул, разрыв, задание, разрыв, тело).
На секциях титула/задания колонтитул без номера страницы; дальше — сквозная нумерация, поле `PAGE`, TNR 12 по центру. После TOC начинается секция тела с номерами.
Если в документе нет TOC — номер ставится на единственную секцию.
**Автотитул** (по умолчанию **выкл.**; CLI `--auto-title` / галочка в GUI; явный `--title` отключает генератор): см. [`docs/title.md`](docs/title.md). Кратко: `md2gost/title_page.py` заполняет bundled `TitleTemplate.docx` из `info_conv.yaml` и/или блока ` ```title `, ФИО/группа — `md2gost.user.json` или `--student`/`--group`. GUI: первый запуск и **Настройки → Студент…**.
**Свойства DOCX** (после склейки титула, перед save): `doc_metadata.apply_document_metadata`. По умолчанию автор = `getuser()`, примечание «Создано при помощи md2gost (ТЗ МИРЭА)», created/modified = сейчас, revision = 1. GUI **Настройки → Метаданные…** / флаги `--doc-*`. Профиль — блок `metadata` в `md2gost.user.json`.
### 5.10. Приложения
- Буквы: А Б В Г Д Е Ж И К … (без Ё З Й О Ч Ь Ы Ъ) — `APPENDIX_LETTERS` в `numberer.py`.
- `## Приложение А Название` оформляется как приложение.
- Если после `# *ПРИЛОЖЕНИЯ` нет перечня, а приложений несколько — Renderer **сам вставляет** список «Приложение А — …». Если автор уже написал перечень — не дублирует.
### 5.11. Промпты для ИИ
| Файл | Назначение |
|------|------------|
| `prompts/generate-md.md` | диалект md2gost vs обычный MD |
| `prompts/generate-mirea-report.md` | полный отчёт ГОСТ / МИРЭА |
| `prompts/generate-pis-custom-report.md` | итоговый отчёт ПИС |
| `prompts/emulate-student.md` | голос: человечный текст, не отчёт ИИ |
В GUI: выбор промпта + чекбоксы схем → в конец дописываются `ai-prompt` и макросы из `md2gost.schemes.json` (`compose_prompt()`).
### 5.12. Сборка и поставка
- `pyproject.toml`: hatchling, пакеты `md2gost`, `md2latex`, `md2fodt`; в wheel вшиваются Template.docx, mml2omml, diagrams, latex/mirea, prompts, docs.
- `md2gost.spec` / `md2gost.fast.spec` — PyInstaller (вшивают `plantuml.jar` и при наличии `vendor/graphviz`).
- `scripts/fetch_plantuml.py` — скачать jar.
- `scripts/fetch_graphviz.py` — скачать portable Graphviz в `md2gost/vendor/graphviz` (для DFD в exe).
- `scripts/md2gost_exe.py` — обёртка exe.
- `scripts/pyi_rth_mplbackend.py` — runtime hook matplotlib для PyInstaller.
- `scripts/check_page_fill.bas` — макрос Word для той же эвристики вёрстки.
- `scripts/md2pdf.ps1` / `md2pdf.sh` — обёртки LaTeX→PDF.
- CI: `.github/workflows/pytest.yml` (Python 3.11, flake8, pytest); `example-generator.yml`.
---
## 6. Карта модулей md2gost и функции кода
Ниже — публичные и важные внутренние функции **уже реализованные**. Приватные `_foo` указаны, если без них не понять модуль.
### 6.1. Точки входа и пайплайн
**`md2gost/__init__.py`**
- `package_dir()` — каталог пакета (и `_MEIPASS` в frozen exe).
**`md2gost/__main__.py`**
- `build_parser()` — argparse.
- `request_from_args(args)``ConvertRequest`.
- `_argv_needs_console(argv)`, `_enable_windows_console()`.
- `main()`.
**`md2gost/pipeline.py`**
- `ConvertRequest`, `ConvertResult`.
- `default_output_path(filename)`, `timestamped_output_path(path)`, `default_template_path()`.
- `open_document(path)` — macOS `open` / Windows `startfile` / `xdg-open`.
- `_fix_front_matter_after_compose(...)` — сброс PAGE на титуле/задании, сквозная нумерация.
- `convert(req, log=None)` — весь конвейер, ошибки в `ConvertResult`, не пробрасывает исключение наружу. Перед save — `apply_document_metadata`.
- `should_launch_gui(filename, gui_flag)`.
- `_CallbackLogHandler` — логи md2gost в GUI/CLI.
**`md2gost/doc_metadata.py`**
- `DocumentMetadata`, `DEFAULT_DOC_COMMENTS`, `AUTHOR_SOURCES`.
- `os_user()`, `clip_core()` (лимит 255 символов python-docx).
- `resolve_document_metadata(...)` — профиль + CLI/request.
- `apply_document_metadata(document, meta)` — core properties + даты + revision=1.
**`md2gost/user_profile.py`**
- `UserProfile` (student, group, metadata), `load_user_profile` / `save_user_profile``md2gost.user.json`.
**`md2gost/converter.py`**
- класс `Converter`: читает md, применяет стили, парсит, нумерует, рендерит.
- `convert()`, свойства `document`, `style_config`, `raw_markdown`, `doc_type`, `heading_numbering`.
### 6.2. Профили и стили
**`md2gost/profiles.py`**
- константы: `DOC_TYPES`, `HEADING_NUMBERING_MODES`, `TOC_MODES`, `TABLE_CONTINUATION_MODES`, `LISTING_CONTINUATION_MODES`, `NUMBERING_SCOPES`, `STYLE_PRESETS`.
- `DocProfile` — поля min/max источников, sectional_biblio, require_graphic_appendix, style_preset, numbering_scope, флаги структуры, `require_apid_kr_structure`.
- `get_profile(doc_type)`.
- `fix_russian_quotes`, `fix_dashes`, `replace_emdash_with_hyphen`.
- `set_emdash_to_hyphen`, `emdash_to_hyphen_enabled`, `dash_separator`.
- `preprocess_markdown`, `separate_biblio_lines`.
- `find_formula_refs``@Формула:` / `@Formula:`.
- `current_year()`.
**`md2gost/style_config.py`**
- `StyleConfigError`.
- `PageSpec.merge/to_dict/require_complete`.
- `ParagraphStyleSpec.merge/to_dict`.
- `StyleConfig.merge/to_dict`.
- `preset_mirea()`, `preset_pis_custom()`, `get_preset(name)`.
- `style_config_from_dict`, `load_styles_file`, `resolve_style_config` (пресет ← рядом с md ← `--styles`).
**`md2gost/styles.py`**
- `apply_style_config(document, config)` — поля, секции, табы TOC, стили абзацев.
- `apply_mirea_styles`, `apply_pis_custom_styles`.
- `apply_document_styles(...)` — пресет + оверлей, возвращает итоговый `StyleConfig`.
- Внутри: `_set_run_font` (блокирует тему Word: Calibri/синий), `_ensure_style`, `_fix_toc_tab_stops`.
**`md2gost/page_geometry.py`**
- глобальные поля `MARGIN_*`, `MARGIN_PRESETS`, `apply_margin_preset`.
- `is_landscape_section`, `apply_section_geometry`, `content_size`.
- `apply_centered_page_footer`, `clear_section_footer`, `ensure_continuous_page_numbers`.
### 6.3. Разбор Markdown
**`md2gost/extended_markdown/`**
- `__init__.py` — Marko + GFM + Extension: Equation, Reference, Caption, Table, TOC, Heading, InlineEquation, Image.
- `heading.py``# *` → ненумерованный.
- `caption.py` — строка `%id текст +listing +landscape`.
- `table.py` — GFM-таблица + `^`/`>` + `_resolve_merge_restarts`.
- `image.py``%id` в title картинки.
- `equation.py` — блочная `$$`.
- `inline_formula.py``$…$`.
- `reference.py``@Тип:id`.
- `toc.py``[TOC]`.
**`md2gost/parser_.py`**
- `Parser.parse()` — пропускает пустые строки; копит `CaptionInfo`; HR без флага игнорирует; иначе `factory.create`.
**`md2gost/renderable_factory.py`**
- `RenderableFactory.create` (singledispatch): Paragraph, Heading, FencedCode/CodeBlock → Listing или DiagramFigure, Equation, List, Table, TOC, ThematicBreak → PageBreak.
- `_create_runs` — жирный/курсив/зачёркивание, код, картинки, инлайн-формулы, `@ссылки`, гиперссылки.
### 6.4. Нумерация и ссылки
**`md2gost/numberer.py`**
- `Numberer(mode="section"|"continuous")`: `enter_section`, `enter_appendix`, `next_number`, `resolve`, `register_label`.
- Режим section: `1.1` / `Б.1`, счётчики сбрасываются на разделе/приложении.
- Режим continuous: `1, 2, 3` на весь документ (ПИС).
**`md2gost/label_pass.py`**
- `LabelRegistry.put/get/get_display` (алиасы Рисунок/Figure/Таблица/…).
- `assign_numbers(renderables, numbered_equations, numbering_scope)`.
- `resolve_pending_in_renderables`, `set_active_registry`, `resolve_reference`.
Формулы нумеруются **только** если на них есть `@Формула:…` в исходнике.
### 6.5. Рендер в DOCX
**`md2gost/renderer.py` — класс `Renderer`**
- `process(renderables)` — основной цикл.
- Секции: фронт без номеров → после TOC тело с PAGE; `_enter_landscape` / `_exit_landscape`.
- `_ensure_appendix_index` — автоперечень приложений.
- Нумерация объектов через `Numberer` (если не `skip_numbering` — в Converter нумерация уже в label_pass).
- Спецзаголовки: СОДЕРЖАНИЕ / СПИСОК — по центру; Введение / Заключение / ПРИЛОЖЕНИЯ — слева как H1.
**`md2gost/layout_tracker.py`**
- `LayoutState` — текущая/оставшаяся высота, номер страницы.
- `LayoutTracker``add_height`, `can_fit_to_page`, `new_page`, `set_page_size` (книга ↔ альбом).
**`md2gost/renderable/`**
| Класс | Файл | Роль |
|--------|------|------|
| `Renderable` | `renderable.py` | абстрактный `render()` |
| `Paragraph` / `Link` | `paragraph.py` | абзац, runs, картинки, ссылки, инлайн-формулы |
| `Heading` | `heading.py` | уровни 19, manual/auto, снятие Word numbering, strip ведущих цифр |
| `Table` | `table.py` | сетка, merge, continuation, `+landscape` |
| `Listing` | `listing.py` | код, Pygments (`DocxParagraphPygmentsFormatter`), continuation |
| `Image` | `image.py` | файл-рисунок + подпись |
| `DiagramFigure` | `diagram.py` | рендер схемы + опциональный Listing исходника |
| `Equation` | `equation.py` | блочная формула OMML + номер справа |
| `Caption` / `CaptionInfo` | `caption.py` | «Рисунок 1.1 — …» |
| `List` | `list.py` | маркированные/нумерованные, вложенность |
| `ToC` | `toc.py` | native field `TOC \o "1-3" \h \z \u` или ручные строки с табами |
| `PageBreak` | `page_break.py` | явный разрыв |
| `RequiresNumbering` | `requires_numbering.py` | интерфейс нумеруемых объектов |
| `ParagraphSizer` / шрифты | `paragraph_sizer.py`, `find_font.py` | оценка высоты абзаца (FreeType) |
**`md2gost/docx_elements.py`**
- `create_table`, `create_table_row`, `create_table_cell`, `apply_cell_merge`, `set_table_box_borders`, фиксация ширины в twips.
**`md2gost/docx_svg.py`**
- `attach_svg_blip(run, inline_shape, svg_path)` — вектор + PNG fallback.
**`md2gost/latex_math.py`**
- `latex_to_omml(latex)` — latex2mathml + XSLT `mml2omml`.
- `inline_omml(omml)` — дроби в линейный вид для инлайна.
**`md2gost/toc_processor.py`**
- `TocProcessor.process` — native: `updateFields` при открытии Word; manual: страницы из `Heading.rendered_page` (СОДЕРЖАНИЕ в оглавление не попадает).
**`md2gost/debugger.py`**
- плавающая сетка страниц в документе (`--debug`): `Debugger`, `add_float_picture`, `new_pic_anchor`.
**`md2gost/util.py`**
- `create_element` — низкоуровневый OOXML.
### 6.6. Библиография
**`md2gost/bibliography.py`**
- `BiblioEntry`, `extract_year`, `parse_biblio_block`, `find_citations`.
- `Bibliography(...)` — ленивая обёртка над renderable (чтобы checker не тянул docx).
**`md2gost/biblio_processor.py`**
- `entries_from_text` — несколько `[n]:` внутри одного абзаца (Marko склеивает строки).
- `extract_bibliography_from_markdown` — плоский список или секции для ВКР.
- `fold_bibliography(renderables, parent, raw_markdown)` — заменяет абзацы списка на `Bibliography`.
**`md2gost/bibliography_renderable.py`** — отрисовка пунктов списка стилем Bibliography.
### 6.7. Диаграммы
**`md2gost/diagram_schemes.py`**
- `DiagramScheme` (id, title, docs, ai-prompt, includes, prefix/postfix, theme).
- `bundled_schemes_path`, `user_schemes_path`, `ensure_user_schemes`.
- `load_schemes_from_path`, `save_schemes`, `load_merged_schemes`.
- `scheme_id_from_lang`, `is_diagram_lang`, `get_scheme`, `get_schemes`, `reload_schemes`, `configure_schemes`.
- `apply_scheme`, `prepare_with_schemes`.
**`md2gost/diagram_includes.py`**
- кэш HTTP `!include`: `resolve_url`, `resolve_include_ref`, `rewrite_http_includes_in_source`, `reset_include_cache`, `cache_entry_count`.
**`md2gost/diagram_renderer.py`**
- `configure_diagrams(...)`, `DiagramConfig`, `DiagramRenderResult`.
- `prepare_source`, `render_diagram`.
- `resolve_plantuml_jar`, `fetch_plantuml_jar`, `iter_plantuml_candidates`, `diagram_engine_status`.
- рендер jar / Kroki / пара png+svg; масштаб `scale` в исходник PlantUML.
- локальные типы `LOCAL_ONLY_TYPES` (`idef0`, `dfd`): Pillow, без jar/Kroki.
**`md2gost/idef0.py`** — DSL IDEF0 + Pillow/SVG.
**`md2gost/dfd.py`** — обёртка [pbauermeister/dfd](https://github.com/pbauermeister/dfd): DSL → DOT → vendor/system Graphviz / Kroki (`write_dfd_outputs`, `fetch_graphviz`).
**`md2gost/diagrams/`** — `schemes.json`, C4 `*.puml`.
### 6.8. Word COM и вёрстка
**`md2gost/word_fix.py`**
- `parse_caption_text`, `find_page_break_row`, `continuation_label`, `caption_style_name`.
- `fix_continuations(path, tables, listings, repeat_header)``FixResult`.
- Внутри: до 5 проходов `Repaginate` + `Split`, рамки листингов, опциональный повтор шапки.
**`md2gost/page_fill_check.py`**
- `PageMetric`, `PageFillIssue`.
- `evaluate_page_fill(pages)` — чистая эвристика (порог пустого низа 40%, пропускает альбом, последнюю страницу, фронт, конец раздела, «в основном рисунок/таблица»).
- `check_docx_page_fill(path)`, `format_page_fill_report`.
### 6.9. Checker (функции проверок)
`md2gost/checker/__init__.py`:
- `check_structure`, `check_apid_kr_structure`, `check_pis_headings`, `check_special_headings`.
- `check_forbidden_abbreviations`, `check_citations_in_intro_conclusion`.
- `check_bibliography`, `check_object_refs`, `check_appendices`.
- `check_continuation_hints`, `check_table_merge`.
- `check_markdown(...)` — оркестратор.
- `format_report(issues)`.
### 6.10. GUI, DnD, справка
**`md2gost/gui.py`**
- `_make_root`, `_combo_values/_combo_key/_display`, `_Tooltip`, `_tip`.
- `Md2GostApp`: меню, окна файлов/студента/метаданных/диаграмм/схем/справки, браузер docs, сборка промпта, DnD, `_collect()``ConvertRequest`, `_convert`.
- `run_gui(initial)`, `main()`.
**`md2gost/dnd.py`**
- `parse_tkdnd_files`, `normalize_drop_paths`, `first_markdown`, `enable_file_drop`.
- Win32: `_WinDropHook`, `_Win32DropApi`, `_query_drop_files`.
**`md2gost/help_content.py`**
- константы `USAGE_HELP`, `SCHEMES_HELP`.
- `prompt_search_dirs`, `load_prompt_catalog`, `scheme_prompt_block`, `compose_prompt`.
- `docs_search_dirs`, `load_docs_catalog`.
---
## 7. md2fodt — что уже есть
Пакет `md2fodt/`.
| Файл | Функции |
|------|---------|
| `__main__.py` | `main()` — CLI: файл, `-o`, `--emdash-to-hyphen` |
| `converter.py` | `convert_md_to_fodt(md, output, emdash_to_hyphen)` |
| `emitter.py` | `emit_body`, `emit_fodt`; эмиттеры heading/paragraph/image/table/code/list/equation; merge `^`/`>` |
| `styles.py` | `styles_xml()`, `automatic_styles_xml()` — TNR 14, поля ГОСТ |
| `escape.py` | `escape_text`, `xml_id` |
Картинки встраиваются base64. Нет диаграмм PlantUML и нет «Продолжение таблицы».
---
## 8. md2latex — что уже есть
Пакет `md2latex/` + шаблон `latex/mirea/` (вендор [mirea-ninja/Latex-Template-for-Report-Diploma-Thesis](https://github.com/mirea-ninja/Latex-Template-for-Report-Diploma-Thesis)).
| Файл | Функции |
|------|---------|
| `__main__.py` | `main()`, `_run_xelatex` (latexmk или 2 прохода xelatex) |
| `converter.py` | `package_template_dir()`, `convert_md_to_latex_project(md, out, titlepage)` — копирует шаблон, пишет `content.tex` |
| `emitter.py` | `emit_document`; `_emit_longtable` с `\endfirsthead` / `\endhead` и «Продолжение таблицы N» |
| `escape.py` | `escape_text`, `escape_verbatim_for_listing`, `latex_label` |
Флаги: `-o` каталог, `--titlepage` PDF титула, `--pdf`, `--xelatex-passes`.
---
## 8.1. word2md — импорт DOCX
Пакет `word2md/`. Эвристика: стили md2gost, иначе ГОСТ-текст подписей/заголовков.
| Файл | Роль |
|------|------|
| `__main__.py` | CLI: `.docx`, `-o`, `--media-dir`, `--keep-toc-pages`, `--pagebreaks` |
| `pipeline.py` | `ImportRequest` / `ImportResult` / `convert_docx()` |
| `walker.py` | обход body, склейка Code/списков, `postprocess_blocks` (продолжения) |
| `classify.py` | Heading / Caption / Code / библио / спецразделы |
| `captions.py` | `Рисунок` / `Таблица` / `Листинг` + `parse_caption_text` из md2gost |
| `tables.py` | merge → `^`/`>`, детект формульной таблицы |
| `omml.py` | OMML → читаемая формула |
| `media.py` | выгрузка `word/media` |
| `emit.py` | IR → диалект md2gost |
| `refs.py` | `Рисунок 1.1``@Рисунок:fig1_1` |
Точки входа также: `python -m md2gost report.docx`, GUI «Импорт DOCX→MD».
---
## 9. Тесты — что покрыто
Каталог `tests/`, CI гоняет `pytest`.
| Файл | Что проверяет |
|------|----------------|
| `test_pipeline.py` | GUI/CLI развилка, пути, DnD, argparse, HR→pagebreak, промпты, docs catalog, listing continuation |
| `test_mirea_tz.py` | Numberer, checker (coursework/PIS/ВКР/АПИД), препроцесс, TOC, заголовки, приложения, библио, page-fill эвристика, стили H1 |
| `test_style_config.py` | merge оверлея, неизвестные ключи, CLI побеждает файл рядом с md, применение к Document |
| `test_table_merge.py` | `^`/`>`, OOXML merge, checker merge, режимы continuation |
| `test_word_fix.py` | разбор подписей, индекс разрыва, COM smoke (если нет Word — мягко) |
| `test_landscape.py` | геометрия альбома, секции, картинки/таблицы/листинги, один section break |
| `test_layout_tracker.py` | страницы и остаток высоты |
| `test_paragraph.py` / `test_paragraph_sizer.py` | абзацы и измерение шрифта |
| `test_diagram_renderer.py` | схемы, кэш, mermaid, svg, jar, `+listing`/`+landscape` |
| `test_idef0.py` | DSL IDEF0, PNG/SVG, интеграция `render_diagram` |
| `test_dfd.py` | DFD data-flow-diagram, mock Graphviz/Kroki, интеграция `render_diagram` |
| `test_md2fodt.py` | escape, каркас FODT, запись файла |
| `test_md2latex.py` | longtable continuation, генерация проекта |
| `test_word2md.py` | подписи, спецзаголовки, @ссылки, продолжения таблиц, DOCX→MD, round-trip |
| `extended_mardown/formula.py` | формулы (unittest) |
Нет полного e2e «открыть Word и сравнить каждую страницу» в Linux CI (шрифты ставятся, Word COM — нет).
---
## 10. Документация и примеры
Пользовательские страницы (те же вшиты в exe, GUI: Справка → Документация):
| Файл | Содержание |
|------|------------|
| `ReadMe.md` | краткий старт репозитория |
| `docs/README.md` | оглавление docs |
| `docs/quickstart.md` | установка, exe, типы |
| `docs/markdown.md` | диалект |
| `docs/schemes.md` | UML/Mermaid, JSON схем |
| `docs/types.md` | профили работ |
| `docs/cli-gui.md` | флаги ↔ GUI |
| `docs/styles.md` | JSON стилей |
| `docs/prompts.md` | ИИ-промпты |
| `docs/word2md.md` | импорт DOCX → Markdown |
| `md2gost/README.md` | справка пакета (подробнее про continuation и диаграммы) |
| `prompts/README.md` | как копировать промпты |
| `examples/example.md`, `examples/pis_custom.md` | образцы |
| `examples/md2gost.styles.json` | пример оверлея стилей |
---
## 11. Зависимости
Обязательные (`pyproject.toml`): python-docx, marko, docxcompose, freetype-py, pillow, requests, latex2mathml, pygments, lxml.
Опционально: pywin32 (Word COM), matplotlib (сборка exe / отладка), tkinterdnd2 (удобный DnD в GUI).
Внешние рантаймы: Java + plantuml.jar **или** Kroki; Graphviz (вшитый/кэш/PATH) для DFD; для PDF — XeLaTeX / latexmk и шрифт Times New Roman.
---
## 12. Что в репозитории, но не продукт
Черновики и чужой код рядом с пакетами. Это **не** часть `pip install` / exe:
- корень: `main.py`, `main12.py`, `mm2.py``mm5.py`, `asd.py`, `parser.py`, `font.py`, `_audit_tmp.py`, `tmp_listing_word.md`, `todo.txt`;
- `ad/` — черновые отчёты;
- `_paco_extract/` — выгрузки методичек ПАЦО;
- `Other_Code/` — справка OOXML, docx-js, скрипты pack/unpack/validate (не импортируется md2gost);
- артефакты сборки `build-fast/`, кэши диаграмм.
`todo.txt` сейчас: «оценки с текстом через сам Word, а не предугадывание» — частично закрыто режимом `word`.
---
## 13. Чего нет / ограничения (честно)
- DFD: пакет `data-flow-diagram` в зависимостях; картинка — вшитый/кэш/PATH Graphviz или Kroki; балансировка уровней не проверяется.
- FODT и LaTeX не догоняют md2gost по GUI, checker, схемам, профилям PIS/АПИД, Word COM.
- «Продолжение таблицы» в чистом DOCX без Word невозможно точно (нет longtable). Без Word — `off` или неточный `legacy`/`caption`.
- `--check-pages` даёт ложные срабатывания; это эвристика.
- Merge ячеек не живёт через границу разрезанной таблицы.
- Цвет текста в стилях не настраивается (всегда чёрный).
- Профиль `paco_custom` упомянут в комментарии `page_geometry`, отдельного типа в `DOC_TYPES` нет.
- Нумерация заголовков H4+ в стилях JSON не описана (в Word уровни 19 у Heading есть).
---
## 14. Типичные сценарии «уже работает»
1. **Практика / курсовая МИРЭА:** `# *ВВЕДЕНИЕ``# 1 …` … список `[1]:``--type practice|coursework --check --strict`.
2. **ВКР:** раздельный список, ссылки `[1.5]`, приложение «Графический материал».
3. **ПИС:** `# Практическая работа №1. …``--type PIS_custom`, сквозные Рисунок 1, 2, 3.
4. **АПИД:** обязательные 2 главы и 2.1–2.4, источники 720.
5. **UML в отчёте:** `%id Подпись` + ` ```uml-c4 ` — PNG/SVG в Word, опционально `+listing` и `+landscape`.
6. **Широкая таблица:** `%id … +landscape`.
7. **Длинная таблица на Windows:** режим `word` → COM режет и пишет «Продолжение Таблицы N».
8. **Свой вуз/кафедра:** `md2gost.styles.json` меняет поля и H1 без правки кода.
9. **Своя схема:** GUI «Шаблоны UML» или JSON с `includes`/`prefix`/`ai-prompt`.
10. **Черновик через ИИ:** промпт из GUI + схемы → `.md` → конвертер.
11. **Только проверить готовый DOCX:** `python -m md2gost report.docx --check-pages`.
12. **Без Word:** `python -m md2fodt` или `python -m md2latex --pdf`.
---
## 15. Поток данных одним абзацем
Пользователь кладёт `.md` (и опционально титул/задание/JSON стилей/схем). `convert()` читает текст, при необходимости гоняет checker, препроцессит кавычки/тире, парсит Marko-расширением в дерево, фабрика делает Renderable, библиография сворачивается в особые абзацы, объектам раздаются номера по профилю, `@ссылки` заменяются на «Рисунок 2.1», Renderer кладёт OOXML в очищенный Template.docx с оценкой высоты страницы, TocProcessor дописывает содержание, pipeline склеивает титул, сохраняет DOCX, при режиме `word` открывает файл в Word и режет таблицы/листинги по настоящей пагинации. GUI делает ровно то же, только параметры собирает из формы.
---
## 16. Где править, если добавлять функцию
| Хочешь | Куда |
|--------|------|
| Новый тип работы | `profiles.PROFILES` + checker + стили пресета |
| Новое поле CLI/GUI | `__main__.build_parser`, `ConvertRequest`, `gui._collect/_apply_request` |
| Новый элемент Markdown | `extended_markdown/` + `RenderableFactory` + класс в `renderable/` |
| Новая проверка ТЗ | `checker/__init__.py` → вызов из `check_markdown` |
| Новая UML-схема «из коробки» | `md2gost/diagrams/schemes.json` (+ `.puml` при необходимости) |
| Новое поле стиля | `style_config.STYLE_FIELD_KEYS` + `ParagraphStyleSpec` + `_apply_paragraph_spec` |
| Паритет FODT/LaTeX | `md2fodt/emitter.py` / `md2latex/emitter.py` |
---
*Файл сгенерирован по состоянию исходников репозитория (пакет 0.1.0). Пользовательские howto — в `docs/`. Этот файл — инвентарь возможностей и кода.*
+93
View File
@@ -0,0 +1,93 @@
# GhostEditor - Markdown to Word Converter
A web-based application that converts Markdown to Word documents with advanced features including real-time preview, styling options, auto-captioning, and table pagination.
## Features
1. **Real-time Conversion**: See your Markdown text convert to Word format in real-time
2. **Styling Options**: Apply different styles to text elements (headings, quotes, code blocks, etc.)
3. **Auto Captioning**: Automatic captions for images, tables, and figures
4. **Table Pagination**: Support for tables that span across pages with repeating headers
5. **Custom Settings**: Configure document settings and styling preferences
## Requirements
- Python 3.7+
- Flask
- python-docx
- markdown
## Installation
1. Install the required packages:
```bash
pip install -r requirements.txt
```
2. Run the application:
```bash
python app.py
```
3. Open your browser and navigate to `http://localhost:5000`
## Usage
1. Enter or paste your Markdown content in the left editor panel
2. See the real-time conversion in the right preview panel
3. Use the settings panel to configure document options:
- Set document title
- Choose default text style
- Enable/disable auto-captioning for images, tables, and figures
- Enable/disable table pagination
4. Use the toolbar buttons to format text directly in the editor
5. Select block type and apply custom styles to specific elements
6. Add custom captions to elements as needed
7. Click "Export to Word" to download your document
## Features Explained
### Real-time Preview
- The application converts Markdown to Word format as you type
- Preview updates automatically as you make changes
### Auto Captioning
- Images automatically receive "Figure X" captions
- Tables automatically receive "Table X" captions
- Captions are numbered sequentially
### Table Pagination
- When enabled, tables that span multiple pages will repeat their header row
- This ensures readability when tables cross page boundaries
### Block Styling
- Select different block types (paragraph, heading, list, etc.)
- Apply specific styles to different content blocks
- Add custom captions to any element
## File Structure
```
/workspace/
├── app.py # Main Flask application
├── requirements.txt # Python dependencies
├── templates/
│ └── index.html # Main HTML template
└── static/
├── style.css # CSS styling
└── script.js # JavaScript functionality
```
## Technologies Used
- **Frontend**: HTML, CSS, JavaScript, Bootstrap 5, Marked.js
- **Backend**: Flask (Python)
- **Document Processing**: python-docx
- **Markdown Processing**: markdown (Python library)
## Customization
You can customize the application by modifying:
- `static/style.css` for visual styling
- `static/script.js` for client-side functionality
- `app.py` for server-side processing and document generation
-74
View File
@@ -1,74 +0,0 @@
# md2gost
Скрипт для генерации docx отчетов в соответствии с ГОСТ из markdown файла.
## Основные возможности
- Генерация отчета;
- ~~Добавление титульной страницы в формате docx~~(not yet);
- Генерация ~~интерактивного~~(not yet) содержания;
- Поддержка сквозной нумерации ~~и кросс-референсинга~~(not yet);
- Автоматическая расстановка картинок, продолжений таблиц и листингов и т.д.
## Пример
Markdown-файл: [example.md](https://github.com/witelokk/md2gost/blob/main/examples/example.md).
Сгенерированный файл в zip архиве (комманда `python -m md2gost --syntax-highlighting example.md`): [example.zip](https://nightly.link/witelokk/md2gost/workflows/example-generator/main/example.zip?h=f65c99d31a9379f44fcc6e923de4a735a271d5aa).
## Установка
```bash
pip install --upgrade git+https://github.com/witelokk/md2gost.git@main
```
Если ваша система приняла стандарт [PEP 668](https://peps.python.org/pep-0668/), используйте [pipx](https://pypa.github.io/pipx/):
```bash
pipx install git+https://github.com/witelokk/md2gost.git@main
```
## Использование
```
(python -m ) md2docx [-h] [-o OUTPUT] [-t TEMPLATE] [--syntax-highlighting | --no-syntax-highlighting] [--debug] filename
```
При отсутствии флага -o, сгенерированый отчет будет иметь имя с названием исходного файла и расширением .md.
## Фичи
### Подписи рисунков, листингов, таблиц
Рисунки:
```markdown
![](path/to/image "Caption text")
```
Таблицы:
```markdown
%uniquename Caption text
| a | b | c |
|---|---|---|
| a | b | c |
```
Листинги:
~~~markdown
%uniquename Caption text
```python
print("hello world")
```
~~~
`uniquename` - уникальное имя для ссылок.
### Заголовки для основных разделов
Для того чтобы у заголовка не было сквозной нумерации (например для заголовка Содержание), используйте
```markdown
# *Содержание
```
### Генерация содержания
```markdown
# *Содержание
[TOC]
```
### Подсветка синтаксиса в листингах
Используйте флаг ```--syntax-highlighting```
BIN
View File
Binary file not shown.
+85 -30
View File
@@ -1,38 +1,93 @@
# GhostEditor / md2gost
# GhostEditor - Markdown to Word Converter
Конвертер **Markdown → DOCX** по методическим указаниям РТУ МИРЭА (ГОСТ 7.32-2017) и профилям ПИС / АПИД. Есть GUI, CLI, импорт **Word → Markdown** (`word2md`) и промпты для генерации `.md` через ИИ.
A web-based application that converts Markdown to Word documents with advanced features including real-time preview, styling options, auto-captioning, and table pagination.
## Быстрый старт
## Features
```bash
pip install -e .
python -m md2gost # GUI
python -m md2gost report.md -o report.docx --type coursework --check
python -m word2md report.docx -o report.md
1. **Real-time Conversion**: See your Markdown text convert to Word format in real-time
2. **Styling Options**: Apply different styles to text elements (headings, quotes, code blocks, etc.)
3. **Auto Captioning**: Automatic captions for images, tables, and figures
4. **Table Pagination**: Support for tables that span across pages with repeating headers
5. **Custom Settings**: Configure document settings and styling preferences
## Requirements
- Python 3.7+
- Flask
- python-docx
- markdown
## Installation
1. Install the required packages:
```bash
pip install -r requirements.txt
```
2. Run the application:
```bash
python app.py
```
3. Open your browser and navigate to `http://localhost:5000`
## Usage
1. Enter or paste your Markdown content in the left editor panel
2. See the real-time conversion in the right preview panel
3. Use the settings panel to configure document options:
- Set document title
- Choose default text style
- Enable/disable auto-captioning for images, tables, and figures
- Enable/disable table pagination
4. Use the toolbar buttons to format text directly in the editor
5. Select block type and apply custom styles to specific elements
6. Add custom captions to elements as needed
7. Click "Export to Word" to download your document
## Features Explained
### Real-time Preview
- The application converts Markdown to Word format as you type
- Preview updates automatically as you make changes
### Auto Captioning
- Images automatically receive "Figure X" captions
- Tables automatically receive "Table X" captions
- Captions are numbered sequentially
### Table Pagination
- When enabled, tables that span multiple pages will repeat their header row
- This ensures readability when tables cross page boundaries
### Block Styling
- Select different block types (paragraph, heading, list, etc.)
- Apply specific styles to different content blocks
- Add custom captions to any element
## File Structure
```
/workspace/
├── app.py # Main Flask application
├── requirements.txt # Python dependencies
├── templates/
│ └── index.html # Main HTML template
└── static/
├── style.css # CSS styling
└── script.js # JavaScript functionality
```
Windows: `build-exe.bat``dist\md2gost.exe` (двойной клик — GUI).
## Technologies Used
## Документация
- **Frontend**: HTML, CSS, JavaScript, Bootstrap 5, Marked.js
- **Backend**: Flask (Python)
- **Document Processing**: python-docx
- **Markdown Processing**: markdown (Python library)
Полная карта проекта (что уже умеет, пайплайны, модули): [`PROJECT.md`](PROJECT.md).
## Customization
Пользовательская документация — в [`docs/`](docs/):
| Раздел | Содержание |
|--------|------------|
| [Быстрый старт](docs/quickstart.md) | Установка, GUI, типы документов |
| [Синтаксис Markdown](docs/markdown.md) | Диалект md2gost vs обычный MD |
| [Схемы и диаграммы](docs/schemes.md) | PlantUML, Mermaid, IDEF0, DFD (Graphviz вшитый/Kroki), `md2gost.schemes.json` |
| [Типы работ](docs/types.md) | coursework, practice, vkr, PIS, APID |
| [CLI и GUI](docs/cli-gui.md) | Флаги и где они в окне |
| [Импорт Word](docs/word2md.md) | DOCX → диалект md2gost |
| [Промпты для ИИ](docs/prompts.md) | Генерация MD, кнопки схем в GUI |
Краткая справка по пакету: [`md2gost/README.md`](md2gost/README.md).
Промпты: [`prompts/`](prompts/).
## Связанные форматы
- FODT (LibreOffice): `python -m md2fodt` — [`md2fodt/`](md2fodt/)
- PDF через LaTeX: [`md2latex/`](md2latex/)
You can customize the application by modifying:
- `static/style.css` for visual styling
- `static/script.js` for client-side functionality
- `app.py` for server-side processing and document generation
-27
View File
@@ -1,27 +0,0 @@
from docx import Document
doc = Document(r"g:\Sync_File\Семестр 3\АИИР\КР\КР_out.docx")
print("=== biblio-ish ===")
for i, p in enumerate(doc.paragraphs):
t = p.text.strip()
style = p.style.name if p.style else None
if "ИСПОЛЬЗОВАНН" in t.upper():
print(i, style, t[:80])
if style == "Bibliography" or (t[:2] in {f"{n}." for n in range(1, 10)} and len(t) > 50):
print(i, style, t[:100])
print("=== double spaces in captions ===")
for p in doc.paragraphs:
if p.style and "Caption" in (p.style.name or "") and " " in p.text:
print(repr(p.text[:90]))
print("=== sections ===")
for i, s in enumerate(doc.sections):
has_page = "PAGE" in s.footer._element.xml
print(i, "PAGE field", has_page)
print("=== Heading 1 ===")
for p in doc.paragraphs:
if p.style and p.style.name == "Heading 1":
print(repr(p.text[:100]))
-988
View File
@@ -1,988 +0,0 @@
УДК 378
ББК 65
К 43
Кириллина Ю.В. Требования к оформлению отчетов по практикам, курсовых работ и
ВКР бакалавров и магистров [Электронный ресурс]: Методические указания / Кириллина
Ю.В., Лагунова А.Д., Бергер Е.Г. — М.: МИРЭА – Российский технологический
университет, 2022. — 1 электрон. опт. диск (CD-ROM)
Методические указания знакомят студентов с требованиями по оформлению учебных
работ, таких как курсовые работы, отчеты по практикам, выпускная квалификационная
работа. Использование методических указаний позволит студентам грамотно оформлять
учебные работы, которые они выполняют согласно учебному плану в процессе обучения.
Данные методические указания основаны на ГОСТ 7.32 – 2017 Система стандартов по
информации, б иблиотечному и издательскому делу. Отчет о научно -исследовательской
работе. Структура и правила и оформления.
Предназначено для студентов по направлени ям подготовки 09.03.03 Прикладная
информатика, 09.0 4.03 Прикладная информатика , а также может быть использовано
студентами других направлений подготовки для получения навыков грамотного оформления
учебных работ.
Методические указания издаются в авторской редакции.
Авторский коллектив: Кириллина Юлия Владимировна, Лагунова Анна Дмитриевна, Бергер
Екатерина Геннадьевна
Рецензенты:
Одинцова Мария Александровна , к.т.н., доцент, доцент кафедры «Предметно -
ориентированные информационные системы» Института кибербезопасности и
цифровых технологий РТУ МИРЭА
Системные требования:
Наличие операционной системы Windows, поддерживаемой производителем.
Наличие свободного места в оперативной памяти не менее 128 Мб.
Наличие свободного места в памяти постоянного хранения (на жестком диске) не менее 30 Мб.
Наличие интерфейса ввода информации.
Дополнительные программные средства: программа для чтения pdf-файлов (Adobe Reader).
Подписано к использованию по решению Редакционно-издательского совета
МИРЭА — Российский технологический университет.
Обьем: 5.39 мб
Тираж: 10
© Кириллина Ю.В., Лагунова А.Д.,
Бергер Е.Г., 2022
© МИРЭА – Российский
технологический университет, 2022
3
СОДЕРЖАНИЕ
ПРЕДИСЛОВИЕ ...................................................................................................... 4
1. СТРУКТУРА УЧЕБНОЙ РАБОТЫ .................................................................... 5
2. ОФОРМЛЕНИЕ ТЕКСТА ДОКУМЕНТА ........................................................ 12
3. ОФОРМЛЕНИЕ ИЛЛЮСТРАЦИЙ И ТАБЛИЦ В УЧЕБНОЙ РАБОТЕ ....... 17
4. ОФОРМЛЕНИЕ ТЕКСТА (ЛИСТИНГА) ПРОГРАММЫ В УЧЕБНОЙ
РАБОТЕ .................................................................................................................. 27
5. ОФОРМЛЕНИЕ СПИСКА ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ В
УЧЕБНОЙ РАБОТЕ ............................................................................................... 30
6. ОФОРМЛЕНИЕ ПРИЛОЖЕНИЙ В УЧЕБНОЙ РАБОТЕ .............................. 34
СПИСОК ИСТОЧНИКОВ И ЛИТЕРАТУРЫ ...................................................... 37
ПРИЛОЖЕНИЕ А .................................................................................................. 38
ПРИЛОЖЕНИЕ Б................................................................................................... 39
ПРИЛОЖЕНИЕ В .................................................................................................. 41
ПРИЛОЖЕНИЕ Г................................................................................................... 42
ПРИЛОЖЕНИЕ Д .................................................................................................. 44
ПРИЛОЖЕНИЕ Е .................................................................................................. 45
4
ПРЕДИСЛОВИЕ
В процессе обучения студентам направлений подготовки 09.03.03, 09.04.03
Прикладная информатика необходимо писать и оформлять курсовые работы, от-
четы по различным видам и типам практик, а также выпускную квалификацион-
ную работу (далее по тексту — учебные работы). Данные методические указания
предназначены для студентов вышеуказанных направлений подготовки.
Целью данных методических указаний является поддержка грамотного
оформления текстовых документов студентами.
Задачами методических указаний являются:
• ознакомление студентов с общей структурой учебных работ, таких как
курсовая работа, отчет по практике, выпускная квалификационная ра-
бота (ВКР);
• ознакомление студентов с правилами оформления учебных работ.
Основой для создания методических указаний является ГОСТ 7.32 — 2017
Система стандартов по информации, библиотечному и издательскому делу.
Отчет о научно-исследовательской работе. Структура и правила и оформления.
Методические указания составлены в соответствии с:
• СМКО МИРЭА 7.5.1/03.П.67- 18 Положение о выпускной квалифика-
ционной работе студентов, обучающихся по образовательным про-
граммам подготовки бакалавров;
• СМКО МИРЭА 7.5.1/03.П.68- 18 Положение о выпускной квалифика-
ционной работе студентов, обучающихся по образовательным про-
граммам подготовки магистров;
• СМКО МИРЭА 7.5.1/04.И.05- 18 Инструкция по организации и прове-
дению курсового проектирования.
5
1. СТРУКТУРА УЧЕБНОЙ РАБОТЫ
Учебная работа студента должна иметь определенную структуру.
Структура конкретной учебной работы регламентируется методическими
указаниями по написанию курсовой работы, методическими указаниями по
написанию отчета по практике, методическими указаниями по написанию ВКР,
которые разрабатываются преподавателями выпускающей кафедры и издаются
редакционно-издательским отделом университета. В се изданные методически е
указания выпускающей кафедры студент может найти на сайте университет а в
разделе Студентам, далее Библиотека.
В тоже время общая структура учебной работы включает в себя:
• ый лист;
• ие;
• ие;
• ие;
• ием;
• ие;
• иков;
• ия.
Титульный лист учебной работы имеет утвержденную форму , выдается
преподавателем, который руководит курсовой работой/практикой/ВКР.
На титульном листе в обязательном порядке проставляется подпись
руководителя учебной работы и студента. В случае, если в кач естве учебной
работы выступает курсовая работа, то на не м необходима подпись второго
преподавателя, участвующего в процедуре защиты курсовой работы. В слу чае,
если в качестве учебной работы выступает ВКР, то на титульном листе
необходима подпись заведующего выпускающей кафедрой. Примеры титульных
листов различных учебных работ приведены в Приложении А .
му и выдается
преподавателем, который руководит курсовой работой/практикой/ВКР.
аботы) — т, в
яется абота). ие подписывается
аботы. совых
абот, а т а к ж е о т ч е т о в п о п р а к т и к е ие обязательно ждается
ой. абот
дополнительно согласуется с директор ом института. Факт принятия
студентом задания к работе подтверждается подписью студента на задании.
6
Кроме подписей в задании должны быть указаны дата утверждения задания
заведующим кафедрой, дата выдачи задания, дата принятия задания к
исполнению. Примеры заданий различных учебных работ приведены в
Приложении Б.
афической
частей в учебной работе устанавливаются методическими указаниями по
написанию курсовой работы, методическими указаниями по написанию отчета
по практике, методическими указаниями по написанию ВКР .
авливается методическими
указаниями по написанию курсовой работы, методическими указаниями по
написанию отчета по практике, методическими указаниями по написанию ВКР ,
а также положениями, приведенными в предисловии данного пособия.
Текст основной части учебной работы еобходимости а азделы,
азделы, пункты . кты имеют заголовки, четко и
ктов.
а листе, который расположен ого листа и
ия, азделов,
иц. иц
а быть
ая.
ия заголовков:
• аздела — я;
• аздела — я;
• ктов — ей.
та,
ые с абзацевого отступа.
аков
ия пишется заголовок.
а б ы т ь в
аздела,
ых точками.
Параметры оформления заголовков в учебной работе представлены в табл.
2.1. Важно обратить внимание на то, что интервалы между заголовками
выставляются в единицах измерения — мм, а не пт.
На рис. 2.1 представлен пример внешнего вида заголовков выпускной
квалификационной работы и курсовой работы с учетом установленных
параметров страниц для учебной работы.
7
Таблица 2.1. Параметры оформления заголовков в учебной работе
Параметр Заголовок
первого урﮦовнﮦя
Заголовок
второго уровня
Заголовок
третьего уровня
ифт
Шрﮦифт Times New Roman
Нﮦачерﮦтанﮦие полужирﮦнﮦый
Подчерﮦкиванﮦие нﮦет
Видоизменﮦенﮦие все прﮦописнﮦые нﮦет нﮦет
Рﮦазмерﮦ 18 пт 16 пт 14 пт
Цвет текста Авто (черﮦнﮦый)
Абзац
Вырﮦавнﮦиванﮦие По левому крﮦаю
Перﮦвая стрﮦока нﮦет
Отступ слева 1,25 см
Отступ спрﮦава 0 мм
Инﮦтерﮦвал перﮦед 0 мм 15 мм 15 мм
Инﮦтерﮦвал после 10 мм 10 мм 10 мм
Междустрﮦочнﮦый
инﮦтерﮦвал
Полуторﮦнﮦый
Положенﮦие нﮦа
ице
Не отрывать от
следующего
С новой страницы
Не отрывать от
следующего
Запрет висящих строк
Нﮦе отрывать от
следующего
Запрет висящих строк
Рисунок 2.1. Пример внешнего вида заголовков
8
азделы «СОДЕРЖАНИЕ», «ВВЕДЕНИЕ», «ЗАКЛЮЧЕНИЕ», «СПИСОК
ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ », «П РИЛОЖЕНИЕ»/«ПРИЛОЖЕНИЯ»
уются.
Разделы «СОДЕРЖАНИЕ» и «СПИСОК ИСПОЛЬЗОВАННЫХ
ИСТОЧНИКОВ» выравниваются по центру страницы.
ие
азделяют точкой.
е Word используется
вкладка «Стили» (рис. 2.2). ﮦ ов
о
ить азу
ия.
Рисунок 2.2. Использование вкладки «Стили» в текстовом редакторе Word
ить
а «Стили» ять
овые стили (рис. 2.3).
ые соответствующими стилями, позволяют
ие.
ктов должны
ии, и
соответственно наоборот. Для обеспечения этого содержание учебной работы
должно формироваться с помощью встроенной функции Оглавление.
ИЕ»,
ием по
у. Важно обратить внимание на значения интервала перед самим
заголовком и после него для того, чтобы обеспечить нужные интервалы между
заголовков и последующими пунктами самого содержания учебной работы.
ю
«Ссылки» → а ю и с
ителя строки «. . . . . . . .» ( рис. 2.4).
9
ить и
овать.
Рисунок 2.3. Редактирование заголовков в текстовом редакторе Word с
использование диалогового окна «Стили»
Рисунок 2.4. Формирование содержания через Автособираемое оглавление
иц,
ом
овить поле».
10
При создании содержания слово ОГЛАВЛЕНИЕ заменяется в ручном
режиме на СОДЕРЖАНИЕ с выставлением необходимых параметров,
характерных для заголовков первого уровня.
ой
текст» без отступа первой строки аю.
я,
ии
ыми буквами (рис. 2.5), аналогично тому, как они
оформлены в учебной работе за исключением того, что полужирное начертание
не применяется.
Рисунок 2.5. Пример оформления содержания в ВКР
11
ии текст попадает иц
кте отсутствует отточие ицы, то часть
очку.
12
2. ОФОРМЛЕНИЕ ТЕКСТА ДОКУМЕНТА
ты учебной работы ой
е листа.
В случае представления учебной работы в бумажном виде она а быть
мата А4.
Учебная работа ых
илами.
Учебная работа проверяется руководителем на соблюдение правил
оформления, в случае несоответствия работы она не допускается до защиты и
выставления оценки, и направляется на доработку.
Текст документа должен быть кратким, четким и не допускать различных
толкований. В докуме нтах должны применяться научно-технические те рмины,
обозначения и определен ия общеп ринятые в научно-технической лите ратуре
Стиль изложения текста в учебной работе строго нау чный, подстиль —
собственно-научный. е допускается:
• ицизмы,
ализмы;
• ия;
• усской
тами и
ая
овка;
• и
.
Текст учебной работы печатается, соблюдая следующие размеры полей:
левое — 30 мм, правое — 10 мм, верхнее и нижнее — 20 мм. Абзацный отступ
должен быть одинаковым по всему тексту и равен 1,25 см [1].
а листах в рамках еще
незаконченного раздела (см. Приложение В).
иц.
Не допускается размещать заголовки в кон це страницы, а основной текст
переносить на следующую страницу.
Текст ифтом
ого цвета , размер шрифта — 14 пт, тип шрифта для основного текста
учебной работы — Times NewтRoman.
ой текст» (табл. 2.1).
13
ифт»,
а знаков абзаца и других скрытых знаков
форматирования ца абзаца и
аки» (ая» →
ифт» → ¶).
Таблица 2.1. Параметры оформления основного текста учебной работы
Параметр Значение
ифт
Шрﮦифт Times New Roman
Нﮦачерﮦтанﮦие Обычнﮦый
Подчерﮦкиванﮦие нﮦет
Видоизменﮦенﮦие нﮦет
Рﮦазмерﮦ 14 пт
Цвет текста Авто (черный)
Абзац
Выравнивание По ширине
Первая строка 1,25 см.
Отступ слева нет
Отступ справа нﮦет
Интервал перﮦед нﮦет
Интервал после нет
Междустрочный интервал Полуторный
Положение на странице Запрет висящих строк
Пробел ставится после любого знака пунктуации, но не перед ним. При этом
не ставятся п робелы после отк рывающих скобок и кавычек, так же как и пе ред
закрывающими скобками и кавычками.
Кавычки в русском тексте (включая список использова нных источ ников)
имеют форму «…», а в английском — "…".
ая.
ицы учебной работы оставляемыми по
ифт — 12 пт).
ицы
е ставится:
• титульный лист;
• ие;
• ие.
е
аки, такие как
«+», «–», «=», «>», «<» и так далее. В тексте их следует писать словами: «плюс»,
ьше».
аки:
14
1. ак дефиса «-» обелами и используется:
• жащих дефисы (во-первых,
физико-математический, кто-либо);
• валов (100-150 Мб).
2. уса «–» ия.
3. е «—обелами и используется в соответствии с
ктуации (Классификаторﮦ —это
систематизированный …).
абские
талов, полугодий,
ами.
ами, ы
иями (… в начале XXI века).
ых
ий (… во 2 разделе, … характерно для середины 1980 годов).
ой и той же
его числа
(…составляет 200, 250, 300 руб.)ица
ﮦ е (… длиной 20-25 см).
иц
ﮦ ами, а числа без
ицы до девяти
— словами (провести испытан ия семи т руб, каждая дли ной 5 м) . ые
обей с ипользованием
запятой при написании (20,5 см).
ый и ый спис ки уются стилем
ой текст».
Таблица 2.2. Параметры оформления списков
Параметр Значение
Марﮦкирﮦованﮦнﮦый список –, ―, ●, ■, ○
Нﮦумерﮦованﮦнﮦый список 1.
а)
Положенﮦие марﮦкерﮦа (нﮦомерﮦа) Отступ 1,25 см
Положенﮦие текста Табуляция после 2,25 см
Отступ 2,25 см
а во всем
ькой
15
чивается — кт в
чивается точкой).
ой буквы и
чиваться точкой (рис. 2.1-2.3).
Рисунок 2.1. Пример 1 оформления списка в учебной работе
Рисунок 2.2. Пример 2 оформления списка в учебной работе
16
Рисунок 2.3. Пример 3 оформления списка в учебной работе
В случае необходимости применения для нумерованного списка строчных
букв русского алфавита, список начинают с буквы «а» (за исключением букв ё,
з, й, о, ч, ъ, ы, ь) [1].
Внутри списка не могут располагаться иллюстрации и таблицы.
При выполнении учебной работы необходимо соблюдать равномерную
плотность и четкость изображения по все й работе. Все линии, буквы, цифры и
знаки должны иметь одинаковую контрастность по всему тексту.
17
3. ОФОРМЛЕНИЕ ИЛЛЮСТРАЦИЙ И ТАБЛИЦ В
УЧЕБНОЙ РАБОТЕ
Количество иллюстраций в учебной работе должно быть достаточ ным для
пояснения излагаемого текста, в некоторых случаях обязательные иллюстрации
регламентируются методическими указаниями по написанию курсовой работы,
методическими указаниями по написанию отчета по практике, методическими
указаниями по написанию ВКР.
о после
ице (по
возможности ближе к соответствующим частям текста учебной работы) с
у без абзацного отступа и первой строки.
ами.
аздела —
ﮦ ﮦ азделяются точкой.
ации
ации (табл. 3.1).
Таблица 3.1. Параметры оформления подписи иллюстраций
Параметр Значение
ифт
Шрифт Times New Roman
Начертание Полужирﮦнﮦый
Подчеркивание нет
Видоизменﮦение нет
Размер 12 пт
Цвет текста Авто (черﮦнﮦый)
Абзац
Выравнивание По центру
Первая строка 0 см
Отступ слева 0 см
Отступ спрﮦава нет
Интервал перﮦед 0 мм
Интервал после 6 мм
Междустрочный интервал Одинарный
Положение на странице Запрет висящих строк
ия
е ставится . Предложение, в котором автор ссылается на
рисунок, должно заканчиваться точкой, а не двоеточие м, т а к к а к э т о является
нарушением правил пунктуации. (рис. 3.1).
ием
а.
18
Рисунок 3.1. Пример оформления рисунка с учетом установленных параметров
страниц учебной работы
углых скобках или
:
• план проекта иллюстрирует диаграмма Ганта (Рисунок 1.1);
• дерево функций представлено на Рисунке 1.1.
о
ия по часовой
а 90 яется с
ую с помощью команды главного меню «Макет» . При
размещении рисунка на отдельной странице с альбомной ориентацией
необходимо установить в Параметрах страницы вертикальное выравнивание
по центру.
Страницы с альбомной ориентацией предназначены только для
рисунков и таблиц, нельзя размещать на них основной текст (Приложение Г,
рис. Г.1-Г.2).
19
Сначала устанавливаются разрывы страницы, начиная со следующей
страницы, а потом меняется ориентация с книжной на альбомную (рис. 3.2-3.3).
Рисунок 3.2. Переход от книжной ориентации к альбомной
Рисунок 3.3. Пример оформления рисунка на странице с альбомной ориентацией
20
В случае, если рисунок завершает раздел, подраздел или пункт
рекомендуется после него сформулиро вать заключительное предложение. Для
раздела это будет заключительное предложение, подводящее итоги по
выполненной работе в соответствующем разделе. Для подраздела или пункта это
будет завершающее предложение, обеспечивающее переход к следующему
подразделу или пункту (рис. 3.4-3.5).
Рисунок 3.4. Пример завершения раздела и переход к следующему
Все иллюстрации должны иметь границы четко по представляемому
рисунку, схеме и т.д., и не допускается пустая, неинформативная часть в
иллюстрации, занимающая место, предназначеннное для основного текста.
На рис. 3.6 представлена правильная и неправильная обрезка границ
иллюстрации.
Вне зависимости от того, каков формат представления учебной работы:
распечатанная бумажная версия или электронный файл, все иллюстрации
должны удовлетворять требованию их четкого воспроизведения, то есть должна
быть обеспечена читабельность иллюстраций без необходимости прибегать к
увеличению масштаба представленного материала.
21
Рисунок 3.5. Пример завершения подраздела и переход к следующему подразделу в
курсовой работе
Рисунок 3.6. Пример правильной обрезки границ иллюстрации (левая часть) и
неправильной обрезки границ илллюстрации (правая часть)
22
Кроме того, рисунки, представляющие собой чертежи, графики, диаграммы,
схемы, помещаемые в учебной работе , должны соответствовать требованиям
стандартов Единой системы конструкторской документации (ЕСКД) .
ия
показателей.
ие таблицы атким.
ад таблицей.
ие таблицы пишется без абзацного отступа и первой строки у
це
е ставится.
ами аздела —
ﮦ ﮦ азделяются точкой.
ом
еобходимости,
ту.
ие ячеек
е допускается.
ед
е Word).
Параметры оформления таблицы в учебной работе представлены в табл. 3.2.
Таблица 3.2. Параметры оформления таблицы
Параметр Надпись таблицы Текст таблицы
ифт
Шрифт Times New Roman
ие Курсив Обычный, полужирный,
курсив
Подчеркиванﮦие нет
Видоизменение нет
Размер 12 пт
Цвет текста Авто (черный)
Абзац
Выравнивание По левому краю По центру, по левому
краю
Первая стрﮦока 0 см
Отступ слева 0 см
Отступ справа нет
Интервал перед 6 мм 0 мм
Интервал после 0 мм
Междустрочный интервал Одинﮦарный
Положение нﮦа странице Запрет висящих строк
23
а все таблицы учебной работы ы ссылки в тексте.
углых скобках или включаются в
ие. Если ссылка на таблицу завершает предложение, то в конце
предложения ставится точка.
ием
углых скобках
:
• далее представлен планﮦпроекта (Таблица 3.1);
• планﮦпроекта представлен в Таблице 3.1 (рис. 3.7).
Рисунок 3.7. Пример представления таблицы
ие
ую
угими частями пишется
адпись таблицы»
(рис. 3.8).
Не допускаются таблицы в одну строчку, а также не допускается оставлять
на странице только заголовок к таблице или заголовок с заголовками граф
(Приложение Г, рис. Г.3).
ации
ед их
ием.
Все таблицы в учебной работе должны быть оформлены единообразно с
точки зрения применяемого стиля для оформления заголовков и подзаголовков
граф, а также строк таблицы.
24
Рисунок 3.8. Пример оформления переноса таблицы в учебной работе
ия,
ия
е
о под
мулой.
ием
мул Microsoft Equation или MathType.
а вкладке «Вставка» →«Уравнение» (рис.
3.9).
Рисунок 3.9. Возможности контекстного меню «Уравнение»
25
Не допускается формулы оформлять как основной текст, основным
шрифтом.
мулы, ивается по
у. а
ока.
а ака
ус ( –ия (×) или
ия яется.
ию.
тов следует
ости, в какой
муле.
ают без абзацного отступа со слова «где»
его.
Значение каждого символа и числового коэффицие нта следует давать с
новой строки, располагая символы один под другим (рис. 3.10).
Рисунок 3.10. Пример оформления последовательности формул в учебной работе
26
Если формула является концом предложения, то ставится точка, если после
формулы предложение продолжается — запятая.
Формулы нумеруются последовательно в пределах раздела арабскими
цифрами в круглых скобках, выровненных по правому краю. Нумеруются только
те формулы, на которые имеются ссылки в тексте.
Ссылки в тексте на номер формулы даются в круглых скобках.
Вне зависимости от способа выполнения учебной работы качество
напечатанного текста и оформления иллюстраций, таблиц, распечаток программ
должно удовлетворять требованию их четкого воспроизведения.
27
4. ОФОРМЛЕНИЕ ТЕКСТА (ЛИСТИНГА) ПРОГРАММЫ В
УЧЕБНОЙ РАБОТЕ
В учебной работе могут содержаться отдельные фрагменты программ (ли-
стинг), разработанных студентом.
Название листинга пишется в одну строку с номером, через тире, с большой
буквы, перед листингом. Точка в конце не ставится. Пример, «Листинг 1.7 —
Процедура открытия программы».
При ссылке на отдельные строки программы они нумеруются в порядке воз-
растания с шагом 10. После ссылки на листинг в фигурных скобках привод ятся
номера строк. Пример «Листинг 3.2 {30, 50, 140}», «Листинг 3.2 {20- 80}».
Листинг оформляется в рамку (рис. 4.1-4.2).
Рисунок 4.1. Пример 1 оформления листинга
Рисунок 4.2. Пример 2 оформления листинга
28
Параметры оформления листинга представлены в табл. 4.1.
Таблица 4.1. Параметры оформления листинга
Листинг
Надпись листинга
Шрифт Шрифт
Шрифт Times New Roman
Начертание Курсив
Размер 12 пт
Цвет текста Авто (черный)
Подчеркивание нет
Видоизменение нет
Интервал
Масштаб 100%
Интервал Обычный
Смещение Нет
Анимация Вид Нет
Абзац Отступы и интервалы
Выравнивание По левому краю
Отступ слева 0 см
Отступ справа 0 см
Первая строка нет
Интервал перед 6 мм
Интервал после 0 мм
Междустрочный Одинарный
Положение на странице Разбивка на страницы Не отрывать от следующего
С новой страницы
Содержание листинга
Шрифт Шрифт
Шрифт Courier New
Начертание Обычный
Размер 10 пт
Цвет текста Авто (черный)
Подчеркивание Нет
Видоизменение нет
Интервал
Масштаб 100%
Интервал Обычный
Смещение Нет
Анимация Вид Нет
Абзац
Отступы и интервалы
Выравнивание По левому краю
Отступ слева 0 см
Отступ справа 0 см
Первая строка 0 см
Интервал перед 0 мм
Интервал после 0 мм
Междустрочный Одинарный
29
Основной текст (строка) после листинга печатается с интервалом перед 6
мм.
Весь текст программы целесообразно выносить в приложени е.
30
5. ОФОРМЛЕНИЕ СПИСКА ИСПОЛЬЗОВАННЫХ
ИСТОЧНИКОВ В УЧЕБНОЙ РАБОТЕ
Все заимствованные части учебной работы (автором которых не является
студент) должны быть сопровождены ссылкой на источник , тип ссылки —
затекстовая (см. ГОСТ Р 7.0.5- 2008). Список должен содержать сведения об
источниках, использованных при составлении учебной работы [1].
Список использованных источников должен включать библиографические
записи на документы, использованные при составлении учебной работы, ссылки
на которые оформляют арабскими цифрами в квадратных скобках.
Сведения об источниках следует располагать в порядке появления ссылок
на источники в тексте учебной работы и нумеровать арабскими цифрами с
точкой и печатать с абзацного отступа в 1,25 см.
При оформлении раздела СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
на первой строке листа печатается соответствующее наименование р аздела,
отформатированное по параметрам для заголовка первого уровня.
Для учебных работ вида курсовой работы или отчета по практике список
использованных источников делить на разделы не требуется. Требованиями к
источникам в данном случае являются следующие:
• количество источников от 5 до 7;
• год издания источника — за последние 5 лет к моменту написания и
представления учебной работы (Приложение Д, рис. Д.1).
В случае выпускной квалификационной рабо ты список использованных
источников делится на разделы, в каждом и которых должно быть представлено
не менее 10 источников, годом издания не больше, чем 5 лет к моменту защиты
выпускной квалификационной работы.
Параметры оформления заголовков разделов в списке использованных
источников представлены в табл. 5.1.
Внутри раздела источники распределяются в порядке упоминания их в
выпускной квалификационной работе и нум еруются (рис. 5.1). В данном случае
номер источника будет состоять из номера разд ела, к которому он относится, и
номера по порядку.
ики следует давать в виде
арабских цифр, заключенных в квадратные скобки, указывающих порядковый
номер источника по списку, например, [1], [2, 3], [1.5], [2.18].
В случае цитирования указываются страницы книги, статьи или другого
источника, из которых взята цитата, например, [2.18, c. 21-25].
31
Таблица 5.1. Параметры оформления заголовков разделов
в списке использованных источников
Параметр Значение
Шрифт
Шрифт Times New Roman
Начертание Обычный
Подчеркивание нет
Видоизменение Все прописные
Размер 14 пт
Цвет текста Авто (черный)
Абзац
Выравнивание По центру
Первая строка нет
Отступ слева 1,25 см.
Отступ справа нет
Интервал перед 6 мм
Интервал после 6 мм
Междустрочный интервал Полуторный
Положение на странице Не отрывать от следующего
Рисунок 5.1. Пример оформления списка использованных источников с делением на
разделы
32
На рис. 5. 2 приведен пример основного текста учебной работы со ссылкой
на источник.
Рисунок 5.2. Пример оформления ссылок в тексте учебной работы
На рис. 5. 3 приведен пример основного текста учебной работы со ссылкой
на источник при цитировании. При цитировании цитируемая фраза ставится в
кавычки.
Рисунок 5.3. Пример оформления ссылок в тексте при цитировании.
33
В основном тексте ВВЕДЕНИЯ и ЗАКЛЮЧЕНИЯ ссылки на
источники не указываются.
Более подробно порядок оформления различных источников представлен в
ГОСТ 7.32 — 2017 Система стандартов по информации, библиотечному и
издательскому делу. Отчет о научно -исследовательской работе. Структура и
правила и оформления. Приложение Е на странице 26 указанного документа.
34
6. ОФОРМЛЕНИЕ ПРИЛОЖЕНИЙ В УЧЕБНОЙ РАБОТЕ
яющий текст учебной работы, допускается помещать в
ие учебной работы а
последующих ее листах.
иложения могут выноситься:
• ом, так и
ия;
• уемого объекта
ия;
• асчеты;
• сложные алгоритмы;
• аботы;
• тов;
• тов;
• экранные формы инормацинной системы;
• листинги программ;
• оизводство
ии).
мата А4. Допускается
мата A3 по ГОСТ 2.301.
В учебной работе приложение может быть одно или несколько.
В случае, если в учебной работе будет только одно приложение , т о н а
следующем листе после списка использованных источников заголовком первого
уровня оформляется заголовок ПРИЛОЖЕНИЕ. И на этом же листе размещается
необходимый дополняющий материал (рис. Д.1, Приложение Д).
В случае необходимости оформить несколько приложений в учебной работе
их а я с А , з а
ﮦ «Приложение А».
ь
ия в
ой текст» (рис.
6.1).
ием
ого стилем
я».
35
Рисунок 6.1. Пример оформления раздела ПРИЛОЖЕНИЯ
а
ﮦ «Приложение А.1», «Приложение А.2», если они связаны по
смыслу.
ый по
ой текст» (рис. 6.2).
Рисунок 6.2. Пример оформления отдельного приложения в составе раздела
ПРИЛОЖЕНИЯ
36
Таблицы и иллюст рации, соде ржащиеся в п риложении, нумеруются
аналогично таблицам и рисунк а м в о сновном тексте учебной работы.
Иллюстрации каждого пр иложения обоз начают отдель ной нумерацией
арабскими циф рами с добавлен ием пе ред циф рой обоз начения приложе ния,
например, «… представлено на Рисунке Б.1», «… отражен в таблице В.1».
В тексте докумен та на все п риложения должн ы быть да ны ссылки.
Приложения располагают в порядке ссылок на них в тексте учебной работы.
При ссылке следует писать слово «П риложение» с большой буквы с
указанием порядкового номера, например «…представлено в Приложении Б».
Перечень материала, оформляемого в виде приложения, определяется
обучающимся совместно с руководителем на основе методических
рекомендаций по курсовой работе, методических рекомендаций по подготовке
отчета по практике, методических рекомендаций по написанию ВКР.
Применительно к ВКР бакалавра или магистра обязательным приложением
к ней является приложение под названием Графический материал, который
представляет собой слайды презентации с основными результатами,
полученными в ходе написания ВКР.
37
СПИСОК ИСТОЧНИКОВ И ЛИТЕРАТУРЫ
1. ГОСТ 7.32 — 2017 Система стандартов по информации,
библиотечному и издательскому делу. Отчет о научно- исследовательской
работе. Структура и правила и оформления — URL:
https://www.rea.ru/ru/org/managements/orgnirupr/Documents/gost_7.32 -2017.pdf
(дата обращения 20.11.2022)
38
ПРИЛОЖЕНИЕ А
Рисунок А.1. Общий вид титульного листа ВКР
Рисунок А.2. Общий вид титульного листа курсовой работы
39
ПРИЛОЖЕНИЕ Б
Рисунок Б.1. Общий вид одностороннего задания на курсовую работу
Рисунок Б.2. Общий вид двустороннего задания на практику
40
Рисунок Б.3. Общий вид двустороннего задания на ВКР (лицевая сторона)
Рисунок Б.4. Общий вид задания на ВКР (оборотная сторона и окончание задания )
41
ПРИЛОЖЕНИЕ В
Рисунок В.1. Пример недопустимой ситуация в учебной работе, полупустая страница при условии,
что подраздел еще не закончился
42
ПРИЛОЖЕНИЕ Г
Рисунок Г.1. Пример 1 неправильного использования страницы с альбомной
ориентацией
Рисунок Г.1. Пример 2 неправильного использования страницы с альбомной
ориентацией
43
Рисунок Г.3. Неверное представление таблицы в учебной работе
44
ПРИЛОЖЕНИЕ Д
Рисунок Д.1. Пример оформления списка использованных источников без деления на
разделы
45
ПРИЛОЖЕНИЕ Е
Рисунок Е.1. Оформление ПРИЛОЖЕНИЯ в учебной работе
46
СВЕДЕНИЯ ОБ АВТОРАХ
Бергер Екатерина Геннадьевна, к.э.н., доцент кафедры практической и при-
кладной информатики Института информационных технологий
Кириллина Юлия Владимировна, к.э.н., доцент, доцент кафедры практиче-
ской и прикладной информатики Института информационных технологий
Лагунова Анна Дмитриевна, к.э.н., доцент кафедры практической и при-
кладной информатики Института информационных технологий
-115
View File
@@ -1,115 +0,0 @@
import pypandoc
from docx import Document
from docx.shared import Pt, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.style import WD_STYLE_TYPE
def apply_custom_formatting(doc):
"""Применяет дополнительное форматирование, которое не может быть обработано Pandoc."""
# Нумерация страниц (простой пример)
# Более сложные колонтитулы лучше настроить в reference.docx
for section in doc.sections:
section.footer.paragraphs[0].text = "\t" # Чтобы номер был по центру или справа, настройте табуляцию
# Добавление рамок к листингам кода, если они не были применены стилем
for paragraph in doc.paragraphs:
if 'листинг' in paragraph.text.lower() or 'listing' in paragraph.text.lower():
# Здесь можно применить стиль, который вы создали, например 'CodeListing'
# paragraph.style = 'CodeListing'
pass # Логика для добавления границ, если нужно
def markdown_to_docx(md_file, docx_file, reference_doc):
"""
Основная функция для конвертации Markdown в DOCX.
"""
# Шаг 1: Используем Pandoc для основной конвертации
pypandoc.convert_file(
md_file,
'docx',
outputfile=docx_file,
extra_args=[f'--reference-doc={reference_doc}', '--toc'] # --toc для создания оглавления
)
# Шаг 2: Открываем созданный документ с помощью python-docx для дальнейшей обработки
doc = Document(docx_file)
# Шаг 3: Вставляем титульный лист в начало документа
# Создаем новый пустой документ для титульного листа
title_doc = Document()
# Добавляем содержимое основного документа после титульного листа
for element in doc.element.body:
title_doc.element.body.append(element)
doc = title_doc
# Шаг 4: Применяем дополнительное форматирование
apply_custom_formatting(doc)
# Шаг 5: Сохраняем финальный документ
doc.save(docx_file)
print(f"Документ '{docx_file}' успешно создан.")
if __name__ == '__main__':
# --- НАСТРОЙКИ ---
markdown_input = 'my_report.md' # Имя вашего входного Markdown файла
docx_output = 'my_report.docx' # Имя выходного DOCX файла
reference_docx = 'samost1.docx' # Имя вашего эталонного документа
# Создаем пример Markdown файла для демонстрации
markdown_content = """
# Введение
Это введение в мою курсовую работу. Текст должен быть отформатирован с использованием стиля "Обычный".
# 1. Структура учебной работы
Здесь описывается структура работы.
## 1.1 Титульный лист
Титульный лист - это первая страница работы.
## 1.2 Содержание
Содержание включает в себя перечень всех разделов.
# 2. Оформление текста документа
Здесь описываются правила оформления текста.
- Первое правило
- Второе правило
- Третье правило
1. Нумерованный список 1
2. Нумерованный список 2
Листинг 1.1 – Пример кода
` ` `python
def hello_world():
print("Hello, World!")
` ` `
Таблица 1.1 - Пример таблицы
| Заголовок 1 | Заголовок 2 |
|-------------|-------------|
| Ячейка 1 | Ячейка 2 |
| Ячейка 3 | Ячейка 4 |
# Заключение
Это заключение.
"""
with open(markdown_input, 'w', encoding='utf-8') as f:
f.write(markdown_content)
# --- ЗАПУСК КОНВЕРТЕРА ---
markdown_to_docx(markdown_input, docx_output, reference_docx)
BIN
View File
Binary file not shown.
-45
View File
@@ -1,45 +0,0 @@
# Введение
Это введение в мою курсовую работу. Текст должен быть отформатирован с использованием стиля "Обычный".
# 1. Структура учебной работы
Здесь описывается структура работы.
## 1.1 Титульный лист
Титульный лист - это первая страница работы.
## 1.2 Содержание
Содержание включает в себя перечень всех разделов.
# 2. Оформление текста документа
Здесь описываются правила оформления текста.
- Первое правило
- Второе правило
- Третье правило
1. Нумерованный список 1
2. Нумерованный список 2
Листинг 1.1 – Пример кода
` ` `python
def hello_world():
print("Hello, World!")
` ` `
Таблица 1.1 - Пример таблицы
| Заголовок 1 | Заголовок 2 |
|-------------|-------------|
| Ячейка 1 | Ячейка 2 |
| Ячейка 3 | Ячейка 4 |
# Заключение
Это заключение.
BIN
View File
Binary file not shown.
+223
View File
@@ -0,0 +1,223 @@
from flask import Flask, render_template, request, send_file, jsonify
import markdown
from docx import Document
from docx.shared import Inches, Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.style import WD_STYLE_TYPE
from docx.oxml.ns import qn
import io
import json
import re
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Global variables for tracking captions and table pagination
image_counter = 0
table_counter = 0
def add_custom_styles(doc):
"""Add custom styles to the document"""
# Heading 1 style
if "Heading 1" not in doc.styles:
h1 = doc.styles.add_style('Heading 1', WD_STYLE_TYPE.PARAGRAPH)
h1.font.name = 'Arial'
h1.font.size = Pt(16)
h1.font.bold = True
h1.paragraph_format.space_after = Pt(12)
# Heading 2 style
if "Heading 2" not in doc.styles:
h2 = doc.styles.add_style('Heading 2', WD_STYLE_TYPE.PARAGRAPH)
h2.font.name = 'Arial'
h2.font.size = Pt(14)
h2.font.bold = True
h2.paragraph_format.space_after = Pt(10)
# Heading 3 style
if "Heading 3" not in doc.styles:
h3 = doc.styles.add_style('Heading 3', WD_STYLE_TYPE.PARAGRAPH)
h3.font.name = 'Arial'
h3.font.size = Pt(12)
h3.font.bold = True
h3.paragraph_format.space_after = Pt(8)
# Quote style
if "Quote" not in doc.styles:
quote = doc.styles.add_style('Quote', WD_STYLE_TYPE.PARAGRAPH)
quote.font.name = 'Arial'
quote.font.size = Pt(11)
quote.font.italic = True
quote.paragraph_format.left_indent = Inches(0.5)
quote.paragraph_format.right_indent = Inches(0.5)
quote.paragraph_format.line_spacing = 1.1
def convert_md_to_docx(markdown_text, config):
"""Convert Markdown text to Word document with custom settings"""
global image_counter, table_counter
image_counter = 0
table_counter = 0
# Create a new document
doc = Document()
# Add custom styles
add_custom_styles(doc)
# Parse markdown into lines
lines = markdown_text.split('\n')
i = 0
while i < len(lines):
line = lines[i].strip()
if line.startswith('# '):
# Heading 1
doc.add_heading(line[2:], level=0)
elif line.startswith('## '):
# Heading 2
doc.add_heading(line[3:], level=1)
elif line.startswith('### '):
# Heading 3
doc.add_heading(line[4:], level=2)
elif line.startswith('> '):
# Blockquote
p = doc.add_paragraph(line[2:], style='Quote')
elif line.startswith('|') and i + 1 < len(lines) and lines[i + 1].strip().startswith('|'):
# Table processing
table_lines = []
while i < len(lines) and lines[i].strip().startswith('|'):
table_lines.append(lines[i].strip())
i += 1
# Process the table
if table_lines:
headers = [cell.strip() for cell in table_lines[0].strip('|').split('|')]
separators = [cell.strip() for cell in table_lines[1].strip('|').split('|')]
rows = []
for j in range(2, len(table_lines)):
row = [cell.strip() for cell in table_lines[j].strip('|').split('|')]
rows.append(row)
# Create table
table = doc.add_table(rows=1, cols=len(headers))
table.style = 'Table Grid'
# Add headers
hdr_cells = table.rows[0].cells
for j, header in enumerate(headers):
if j < len(hdr_cells):
hdr_cells[j].text = header
# Add data rows
for row_data in rows:
row_cells = table.add_row().cells
for j, cell_data in enumerate(row_data):
if j < len(row_cells):
row_cells[j].text = cell_data
# Add table caption if enabled
if config.get('autoCaptionTables', True):
table_counter += 1
caption_para = doc.add_paragraph()
caption_run = caption_para.add_run(f'Table {table_counter}: ')
caption_run.italic = True
caption_run.font.size = Pt(10)
caption_run.font.name = 'Arial'
caption_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
elif line.startswith('```'):
# Code block
code_lines = []
lang = line[3:] if len(line) > 3 else ''
i += 1
while i < len(lines) and not lines[i].startswith('```'):
code_lines.append(lines[i])
i += 1
code_block = '\n'.join(code_lines)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(code_block)
run.font.name = 'Courier New'
run.font.size = Pt(10)
# Apply shading to the paragraph - simplified approach
# For now, just add the code block as formatted text
pass
elif line.startswith('- ') or line.startswith('* '):
# List item
p = doc.add_paragraph(line[2:], style='List Bullet')
elif line.startswith('!['):
# Image with potential caption
# Extract image info: ![alt text](url)
match = re.match(r'!\[(.*?)\]\((.*?)\)', line)
if match:
alt_text = match.group(1)
img_url = match.group(2)
# Add image if it's a valid local file
try:
# For this example, we'll just add a placeholder since we don't have actual image files
p = doc.add_paragraph('Image Placeholder: ' + alt_text)
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Add caption if enabled
if config.get('autoCaptionImages', True):
image_counter += 1
caption_para = doc.add_paragraph()
caption_run = caption_para.add_run(f'Figure {image_counter}: {alt_text}')
caption_run.italic = True
caption_run.font.size = Pt(10)
caption_run.font.name = 'Arial'
caption_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
except:
# If image can't be added, just add alt text
doc.add_paragraph(alt_text)
elif line == '':
# Empty line - add spacing
doc.add_paragraph('')
else:
# Regular paragraph
if line:
doc.add_paragraph(line)
i += 1
return doc
@app.route('/')
def index():
return render_template('index.html')
@app.route('/export', methods=['POST'])
def export():
markdown_text = request.form.get('markdown', '')
config_json = request.form.get('config', '{}')
try:
config = json.loads(config_json)
except:
config = {}
# Convert markdown to docx
doc = convert_md_to_docx(markdown_text, config)
# Save to BytesIO object
file_stream = io.BytesIO()
doc.save(file_stream)
file_stream.seek(0)
# Return the file for download
return send_file(
file_stream,
as_attachment=True,
download_name='document.docx',
mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
-90
View File
@@ -1,90 +0,0 @@
@echo off
setlocal EnableExtensions
cd /d "%~dp0"
chcp 65001 >nul 2>&1
set "DO_PAUSE=1"
set "PYI_CLEAN="
if /i "%~1"=="nopause" set "DO_PAUSE=0"
if /i "%~2"=="nopause" set "DO_PAUSE=0"
if /i "%~1"=="clean" set "PYI_CLEAN=--clean"
if /i "%~2"=="clean" set "PYI_CLEAN=--clean"
echo === md2gost: быстрая сборка exe, onefile, шрифты и plantuml.jar ===
echo Каталог: %CD%
echo Spec: md2gost.fast.spec
echo Python: 3.11 ^(ищем, не берём первый python из PATH^)
echo Кэш: build-fast\ без --clean, пока не передадите clean
echo.
call "%~dp0build-find-python311.bat"
if errorlevel 1 goto :nopython
if not defined PYEXE goto :nopython
echo [1/4] Зависимости ...
"%PYEXE%" -c "import PyInstaller, matplotlib, docx, marko, lxml, pygments, PIL, freetype, latex2mathml, requests, docxcompose, tkinterdnd2" 1>nul 2>nul
if not errorlevel 1 goto :deps_ok
echo Ставлю проект + PyInstaller + matplotlib + tkinterdnd2 ...
"%PYEXE%" -m pip install -q -e . "pyinstaller>=6.0" "matplotlib>=3.7" "tkinterdnd2"
if errorlevel 1 goto :pipfail
:deps_ok
if not exist "md2gost\Template.docx" goto :notemplate
echo [2/4] PlantUML jar + Graphviz + Mermaid assets ...
"%PYEXE%" scripts\fetch_plantuml.py
if not exist "md2gost\vendor\plantuml.jar" goto :nojar
"%PYEXE%" scripts\fetch_graphviz.py
if not exist "md2gost\vendor\graphviz\bin\dot.exe" (
echo Предупреждение: Graphviz нет — в exe DFD пойдёт через kroki.io / PATH.
)
if not exist "md2gost\diagrams\mermaid.min.js" (
"%PYEXE%" scripts\fetch_mermaid.py
)
echo [3/4] PyInstaller onefile, кэш build-fast ...
"%PYEXE%" -m PyInstaller --noconfirm %PYI_CLEAN% --workpath build-fast --distpath dist md2gost.fast.spec
if errorlevel 1 goto :pyifail
if not exist "dist\md2gost.exe" goto :noexe
echo.
echo [4/4] Готово:
echo %CD%\dist\md2gost.exe
echo.
echo Двойной клик — GUI. Из консоли: md2gost.exe report.md -o report.docx
echo Повторно без clean — быстрее за счёт кэша Analysis.
echo Полный пересбор: build-exe-fast.bat clean
echo.
if "%DO_PAUSE%"=="1" pause
exit /b 0
:nopython
echo Нужен именно Python 3.11. Через uv без системного 3.11: build-exe-uvx.bat
goto :fail
:pipfail
echo Не удалось поставить зависимости.
goto :fail
:notemplate
echo Нет md2gost\Template.docx — сборка бессмысленна.
goto :fail
:nojar
echo Нет md2gost\vendor\plantuml.jar — portable exe без jar не собираем.
goto :fail
:pyifail
echo PyInstaller завершился с ошибкой.
goto :fail
:noexe
echo dist\md2gost.exe не появился.
goto :fail
:fail
echo.
echo Сборка не удалась.
if "%DO_PAUSE%"=="1" pause
exit /b 1
-128
View File
@@ -1,128 +0,0 @@
@echo off
setlocal EnableExtensions
cd /d "%~dp0"
chcp 65001 >nul 2>&1
set "DO_PAUSE=1"
set "WANT_CLEAN=0"
set "FAST=0"
:parse_args
if "%~1"=="" goto :args_done
if /i "%~1"=="nopause" set "DO_PAUSE=0"
if /i "%~1"=="clean" set "WANT_CLEAN=1"
if /i "%~1"=="fast" set "FAST=1"
shift
goto :parse_args
:args_done
set "PYI_SPEC=md2gost.spec"
set "PYI_WORK="
set "PYI_DIST="
set "PYI_CLEAN=--clean"
if "%FAST%"=="1" (
set "PYI_SPEC=md2gost.fast.spec"
set "PYI_WORK=--workpath build-fast"
set "PYI_DIST=--distpath dist"
set "PYI_CLEAN="
if "%WANT_CLEAN%"=="1" set "PYI_CLEAN=--clean"
)
if "%FAST%"=="1" (
echo === md2gost: сборка exe через uvx, Python 3.11, fast spec ===
echo Spec: md2gost.fast.spec
echo Кэш: build-fast\
) else (
echo === md2gost: сборка exe через uvx, Python 3.11 ===
echo Spec: md2gost.spec
)
echo Каталог: %CD%
echo uvx сам возьмёт CPython 3.11 ^(скачает, если ещё нет^).
echo.
set "UVX_BIN="
for /f "delims=" %%I in ('where uvx 2^>nul') do (
set "UVX_BIN=%%I"
goto :got_uvx
)
if exist "%USERPROFILE%\.local\bin\uvx.exe" set "UVX_BIN=%USERPROFILE%\.local\bin\uvx.exe"
if defined UVX_BIN goto :got_uvx
if exist "%USERPROFILE%\.cargo\bin\uvx.exe" set "UVX_BIN=%USERPROFILE%\.cargo\bin\uvx.exe"
if defined UVX_BIN goto :got_uvx
echo uvx не найден. Установите uv: https://docs.astral.sh/uv/getting-started/installation/
echo powershell: irm https://astral.sh/uv/install.ps1 ^| iex
goto :fail
:got_uvx
echo uvx: %UVX_BIN%
"%UVX_BIN%" --python 3.11 python -c "import sys; print('CPython', sys.version.split()[0], sys.executable)"
if errorlevel 1 goto :nopython
if not exist "md2gost\Template.docx" goto :notemplate
echo [1/4] PlantUML jar + Graphviz + Mermaid assets ...
"%UVX_BIN%" --python 3.11 --isolated --with-editable . -- python scripts\fetch_plantuml.py
if "%FAST%"=="1" (
if not exist "md2gost\vendor\plantuml.jar" goto :nojar
) else (
if not exist "md2gost\vendor\plantuml.jar" (
echo Предупреждение: plantuml.jar нет — в exe UML пойдёт через kroki.io.
)
)
"%UVX_BIN%" --python 3.11 --isolated --with-editable . -- python scripts\fetch_graphviz.py
if not exist "md2gost\vendor\graphviz\bin\dot.exe" (
echo Предупреждение: Graphviz нет — в exe DFD пойдёт через kroki.io / PATH.
)
if not exist "md2gost\diagrams\mermaid.min.js" (
"%UVX_BIN%" --python 3.11 --isolated --with-editable . -- python scripts\fetch_mermaid.py
)
if "%FAST%"=="0" (
if not exist "md2gost\diagrams\mermaid.min.js" (
echo Предупреждение: mermaid.min.js нет — браузерный Mermaid в exe без assets.
)
)
echo [2/4] Эфемерное окружение: проект + matplotlib + PyInstaller ^(CPython 3.11^) ...
echo [3/4] PyInstaller, один файл ...
"%UVX_BIN%" --python 3.11 --isolated --from "pyinstaller>=6.0" --with-editable . --with "matplotlib>=3.7" --with "tkinterdnd2" -- pyinstaller --noconfirm %PYI_CLEAN% %PYI_WORK% %PYI_DIST% %PYI_SPEC%
if errorlevel 1 goto :pyifail
if not exist "dist\md2gost.exe" goto :noexe
echo.
echo [4/4] Готово:
echo %CD%\dist\md2gost.exe
echo.
echo Двойной клик — GUI. Из консоли: md2gost.exe report.md -o report.docx
echo Быстрый кэш: build-exe-uvx.bat fast
echo Полный пересбор fast: build-exe-uvx.bat fast clean
echo.
if "%DO_PAUSE%"=="1" pause
exit /b 0
:nopython
echo uvx не смог запустить Python 3.11.
goto :fail
:notemplate
echo Нет md2gost\Template.docx — сборка бессмысленна.
goto :fail
:nojar
echo Нет md2gost\vendor\plantuml.jar — portable exe без jar не собираем.
goto :fail
:pyifail
echo PyInstaller завершился с ошибкой.
goto :fail
:noexe
echo dist\md2gost.exe не появился.
goto :fail
:fail
echo.
echo Сборка не удалась.
if "%DO_PAUSE%"=="1" pause
exit /b 1
-77
View File
@@ -1,77 +0,0 @@
@echo off
setlocal EnableExtensions
cd /d "%~dp0"
chcp 65001 >nul 2>&1
echo === md2gost: сборка exe ===
echo Каталог: %CD%
echo Python: 3.11 ^(ищем, не берём первый python из PATH^)
echo.
call "%~dp0build-find-python311.bat"
if errorlevel 1 goto :nopython
if not defined PYEXE goto :nopython
echo [1/4] Зависимости проекта + PyInstaller + matplotlib ...
"%PYEXE%" -m pip install -q -e . "pyinstaller>=6.0" "matplotlib>=3.7" "tkinterdnd2"
if errorlevel 1 goto :pipfail
if not exist "md2gost\Template.docx" goto :notemplate
echo [2/4] PlantUML jar + Graphviz + Mermaid assets ...
"%PYEXE%" scripts\fetch_plantuml.py
if not exist "md2gost\vendor\plantuml.jar" (
echo Предупреждение: plantuml.jar нет — в exe UML пойдёт через kroki.io.
)
"%PYEXE%" scripts\fetch_graphviz.py
if not exist "md2gost\vendor\graphviz\bin\dot.exe" (
echo Предупреждение: Graphviz нет — в exe DFD пойдёт через kroki.io / PATH.
)
if not exist "md2gost\diagrams\mermaid.min.js" (
"%PYEXE%" scripts\fetch_mermaid.py
)
if not exist "md2gost\diagrams\mermaid.min.js" (
echo Предупреждение: mermaid.min.js нет — браузерный Mermaid в exe без assets.
)
echo [3/4] PyInstaller, один файл, без консоли; CLI подцепит консоль сам ...
"%PYEXE%" -m PyInstaller --noconfirm --clean md2gost.spec
if errorlevel 1 goto :pyifail
if not exist "dist\md2gost.exe" goto :noexe
echo.
echo [4/4] Готово:
echo %CD%\dist\md2gost.exe
echo.
echo Двойной клик — GUI. Из консоли: md2gost.exe report.md -o report.docx
echo.
if /i "%~1"=="nopause" goto :eof
pause
exit /b 0
:nopython
echo Нужен именно Python 3.11. Через uv без системного 3.11: build-exe-uvx.bat
goto :fail
:pipfail
echo Не удалось поставить зависимости.
goto :fail
:notemplate
echo Нет md2gost\Template.docx — сборка бессмысленна.
goto :fail
:pyifail
echo PyInstaller завершился с ошибкой.
goto :fail
:noexe
echo dist\md2gost.exe не появился.
goto :fail
:fail
echo.
echo Сборка не удалась.
if /i not "%~1"=="nopause" pause
exit /b 1
-90
View File
@@ -1,90 +0,0 @@
@echo off
REM Вызывается через call из build-exe.bat / build-exe-fast.bat.
REM На успехе: PYEXE = полный путь к python.exe 3.11, errorlevel 0.
REM Если 3.11 нет: PYEXE пустой, errorlevel 1.
set "PYEXE="
where py >nul 2>&1
if not errorlevel 1 (
for /f "delims=" %%I in ('py -3.11 -c "import sys; print(sys.executable)" 2^>nul ^| findstr /i /c:"python.exe"') do call :consider "%%I"
)
if defined PYEXE goto :ok
where uv >nul 2>&1
if not errorlevel 1 (
for /f "delims=" %%I in ('uv python find 3.11 2^>nul') do call :consider "%%I"
)
if defined PYEXE goto :ok
where python3.11 >nul 2>&1
if not errorlevel 1 (
for /f "delims=" %%I in ('where python3.11 2^>nul') do call :consider "%%I"
)
if defined PYEXE goto :ok
where python >nul 2>&1
if not errorlevel 1 (
for /f "delims=" %%I in ('where python 2^>nul') do call :consider "%%I"
)
if defined PYEXE goto :ok
where python3 >nul 2>&1
if not errorlevel 1 (
for /f "delims=" %%I in ('where python3 2^>nul') do call :consider "%%I"
)
if defined PYEXE goto :ok
if defined LOCALAPPDATA (
for /d %%D in ("%LOCALAPPDATA%\Programs\Python\Python311*") do call :consider "%%D\python.exe"
for /d %%D in ("%LOCALAPPDATA%\uv\python\cpython-3.11.*-windows*") do call :consider "%%D\python.exe"
)
if defined PYEXE goto :ok
if defined APPDATA (
for /d %%D in ("%APPDATA%\uv\python\cpython-3.11.*-windows*") do call :consider "%%D\python.exe"
)
if defined PYEXE goto :ok
if defined USERPROFILE (
for /d %%D in ("%USERPROFILE%\.local\share\uv\python\cpython-3.11.*-windows*") do call :consider "%%D\python.exe"
)
if defined PYEXE goto :ok
call :consider "%ProgramFiles%\Python311\python.exe"
if defined PYEXE goto :ok
call :consider "%ProgramFiles(x86)%\Python311-32\python.exe"
if defined PYEXE goto :ok
call :consider "C:\Python311\python.exe"
if defined PYEXE goto :ok
where uv >nul 2>&1
if errorlevel 1 goto :miss
echo Python 3.11 не найден, ставлю через uv python install 3.11 ...
uv python install 3.11
if errorlevel 1 goto :miss
for /f "delims=" %%I in ('uv python find 3.11 2^>nul') do call :consider "%%I"
if defined PYEXE goto :ok
:miss
echo Python 3.11 не найден.
echo Поставьте CPython 3.11 ^(python.org / py -3.11^) либо uv ^(тогда: uv python install 3.11^).
echo Либо соберите через build-exe-uvx.bat — uvx сам подтянет 3.11.
set "PYEXE="
exit /b 1
:ok
echo Python 3.11: %PYEXE%
"%PYEXE%" --version
exit /b 0
:consider
if defined PYEXE goto :eof
if "%~1"=="" goto :eof
echo "%~1" | findstr /i "WindowsApps" >nul
if not errorlevel 1 goto :eof
if not exist "%~1" goto :eof
"%~1" -c "import sys; raise SystemExit(0 if sys.version_info[:2] == (3, 11) else 1)" 1>nul 2>nul
if errorlevel 1 goto :eof
set "PYEXE=%~1"
goto :eof
-4
View File
@@ -1,4 +0,0 @@
tests/_idef0_preview.png
tests/_idef0_preview.svg
tests/_idef0_preview_a0.png
tests/_idef0_preview_a0.svg
-22
View File
@@ -1,22 +0,0 @@
# Документация md2gost
Конвертер Markdown → DOCX для учебных работ (ТЗ МИРЭА / ГОСТ 7.32, ПИС, АПИД).
## Содержание
1. [Быстрый старт](quickstart.md) — установка, первое окно, exe
2. [Синтаксис Markdown](markdown.md) — чем диалект отличается от обычного MD
3. [Схемы и диаграммы](schemes.md) — UML, Mermaid, IDEF0, DFD (вшитый Graphviz / Kroki), настраиваемые схемы
4. [ArchiMate 3.2](archimate.md) — генерация схем (макросы PlantUML, связи, viewpoints)
5. [Типы документов](types.md) — coursework, practice, vkr, PIS_custom, APID_coursework
6. [CLI и GUI](cli-gui.md) — флаги и соответствие в интерфейсе
7. [Автотитульник](title.md) — `info_conv.yaml`, блок `title`, ФИО/группа
8. [Кастомные стили (JSON)](styles.md) — оверлей полей и стилей абзацев
9. [Промпты для ИИ](prompts.md) — генерация `.md`, расширение промпта схемами
10. [Импорт Word → Markdown](word2md.md) — DOCX в диалект md2gost (word2md)
Исходный код конвертера: [`md2gost/`](../md2gost/). Примеры: [`examples/`](../examples/).
Полная карта репозитория (архитектура, все функции CLI/GUI и модули кода): [`PROJECT.md`](../PROJECT.md).
В GUI: **Справка → Документация** — тот же набор страниц (вшит в exe).
-662
View File
@@ -1,662 +0,0 @@
# ArchiMate 3.2: гайд по генерации схем (PlantUML + md2gost)
Учебный гайд по **правильной генерации** диаграмм ArchiMate® 3.2 в PlantUML для отчётов md2gost.
Язык — **только 3.2** (документ C226). ArchiMate 4 не используется.
ArchiMate® — зарегистрированный товарный знак The Open Group. Текст гайда — учебный пересказ корпуса PDF и документации PlantUML, **не** копия спецификации.
## Содержание
1. [Как рисовать в md2gost](#1-как-рисовать-в-md2gost)
2. [Каркас языка 3.2](#2-каркас-языка-32)
3. [Каталог элементов → макросы PlantUML](#3-каталог-элементов--макросы-plantuml)
4. [Связи](#4-связи)
5. [Что с чем связывать](#5-что-с-чем-связывать)
6. [Viewpoints](#6-viewpoints)
7. [Синтаксис PlantUML](#7-синтаксис-plantuml)
8. [Чеклист для ИИ](#8-чеклист-для-ии)
9. [Готовые шаблоны](#9-готовые-шаблоны)
10. [Антипаттерны](#10-антипаттерны)
11. [Источники и границы корпуса](#11-источники-и-границы-корпуса)
---
## 1. Как рисовать в md2gost
Оградка схемы: `` ```uml-archimate `` или `` ```archimate ``.
В теле пишите **только макросы** Archimate-PlantUML. Без `@startuml`, без `@enduml`, без `!include` — схема `archimate` добавит их сама.
````markdown
%arch1 Слоистая архитектура портала +landscape
```uml-archimate
LAYOUT_TOP_DOWN()
Business_Actor(student, "Студент")
Business_Process(enroll, "Подача заявки")
Application_Service(portalSvc, "Портал заявок")
Application_Component(portal, "Web-портал")
Rel_Assignment(student, enroll)
Rel_Serving(portalSvc, enroll)
Rel_Realization(portal, portalSvc)
```
````
| Флаг у `%подписи` | Смысл |
|-------------------|--------|
| `+landscape` | Альбомная страница под широкий рисунок |
| `+listing` | Рядом показать исходник диаграммы |
Широкие Layered / Application Cooperation почти всегда с `+landscape`.
---
## 2. Каркас языка 3.2
### 2.1. Модель, концепт, элемент, связь
По sample C226 (§23):
- **Model** — набор концептов.
- **Concept** — либо **element**, либо **relationship**.
- **Element** — behavior, structure, motivation или composite (абстрактные классы; в модели не рисуются сами по себе).
- **Relationship** — связь source → target; класс: structural / dependency / dynamic / other.
- **Relationship connector (Junction)** — соединяет две или более связи **одного** типа.
Язык намеренно мал: «80 % практических случаев», без попытки покрыть всех пользователей сразу (§3.1).
### 2.2. Три core-слоя
| Слой | Что показывает |
|------|----------------|
| **Business** | Бизнес-сервисы для клиентов; процессы и акторы, которые их реализуют |
| **Application** | Прикладные сервисы и приложения, поддерживающие бизнес |
| **Technology** | ИТ и OT: обработка, хранение, сети; также физика (сооружения, оборудование, материалы, распределительные сети) |
Структура моделей на слоях похожа: те же виды элементов и связей, разная природа и гранулярность.
### 2.3. Аспекты (подлежащее — сказуемое — дополнение)
| Аспект | Роль | Примеры |
|--------|------|---------|
| **Active structure** | Кто/что действует | Actor, Role, Component, Node, Device |
| **Behavior** | Что делается | Process, Function, Interaction, Service, Event |
| **Passive structure** | Над чем работают | Business Object, Data Object, Artifact, Material |
| **Motivation** | Зачем | Stakeholder, Driver, Goal, Requirement… |
| **Composite** | Группировка / место | Grouping, Location, Product |
На листах Виерды (не стандарт Open Group): синий = активная структура, жёлтый = поведение, зелёный = пассивная. **Официальный ArchiMate бесцветен**; цвета — соглашение инструментов (в PlantUML — палитры слоёв `#Business`, `#Application`, …).
### 2.4. Full framework
К core добавляются (van den Berg §2.4 / full framework C226):
- слой **Strategy**;
- слой **Implementation & Migration**;
- аспект **Motivation**.
### 2.5. Два главных межслойных моста (§3.3)
1. **Serving** (раньше *used by*): сервис (или элемент) **предоставляет функциональность** другому. Сервис нижнего/соседнего слоя обслуживает потребителя. Сервис может обслуживать и элемент **того же** слоя.
2. **Realization**: более конкретное (часто ниже) **реализует** более абстрактное (часто выше): например приложение реализует прикладной сервис, сервис/процесс реализует требование или capability.
Каноническая цепочка внутри слоя:
```text
Active structure —Assignment→ internal behavior (Process/Function)
internal behavior —Realization→ Service (external behavior)
Service —Serving→ consumer (Role / Process / Component …)
behavior —Access→ passive structure
```
---
## 3. Каталог элементов → макросы PlantUML
Определения — **N221** (Reference Cards). Макросы — Archimate-PlantUML 3.2.1.
Формат: `Category_ElementName(alias, "Подпись")`.
Alias — латиница (`student`, `crm`). Не используйте `end`, `start`, `group` как alias.
### 3.1. Motivation
| Элемент | Макрос | Определение (N221) |
|---------|--------|-------------------|
| Stakeholder | `Motivation_Stakeholder` | Роль индивида, команды или организации, заинтересованной в эффектах архитектуры |
| Driver | `Motivation_Driver` | Внешнее/внутреннее условие, побуждающее задать цели и изменения |
| Assessment | `Motivation_Assessment` | Результат анализа положения дел относительно driver |
| Goal | `Motivation_Goal` | Высокоуровневое намерение / желаемое конечное состояние |
| Outcome | `Motivation_Outcome` | Конечный результат / эффект некоторого положения дел |
| Principle | `Motivation_Principle` | Общее свойство, применимое к любой системе в контексте |
| Requirement | `Motivation_Requirement` | Потребность: свойство конкретной системы в архитектуре |
| Constraint | `Motivation_Constraint` | Ограничение на архитектуру, реализацию или процесс внедрения |
| Meaning | `Motivation_Meaning` | Знание/интерпретация концепта в контексте |
| Value | `Motivation_Value` | Относительная ценность / полезность концепта |
### 3.2. Strategy
| Элемент | Макрос | Определение (N221) |
|---------|--------|-------------------|
| Resource | `Strategy_Resource` | Актив, которым владеют или управляют |
| Capability | `Strategy_Capability` | Способность, которой обладает активная структура |
| Value Stream | `Strategy_ValueStream` | Последовательность активностей, создающая результат для клиента/стейкхолдера |
| Course of Action | `Strategy_CourseOfAction` | Подход/план настройки capabilities и resources для достижения цели |
### 3.3. Business
| Элемент | Макрос | Аспект | Определение (N221) |
|---------|--------|--------|-------------------|
| Business Actor | `Business_Actor` | Active | Сущность, способная выполнять поведение |
| Business Role | `Business_Role` | Active | Ответственность за поведение; роль актора |
| Business Collaboration | `Business_Collaboration` | Active | Агрегат ≥2 внутренних active structure для коллективного поведения |
| Business Interface | `Business_Interface` | Active | Точка доступа, где бизнес-сервис доступен среде |
| Business Process | `Business_Process` | Behavior | Последовательность бизнес-поведения к конкретному результату |
| Business Function | `Business_Function` | Behavior | Набор поведения по критериям (ресурсы/компетенции) |
| Business Interaction | `Business_Interaction` | Behavior | Коллективное поведение ≥2 акторов/ролей/коллабораций |
| Business Event | `Business_Event` | Behavior | Изменение состояния на бизнес-уровне |
| Business Service | `Business_Service` | Behavior | Явно определённое поведение, доступное среде |
| Business Object | `Business_Object` | Passive | Концепт предметной области |
| Contract | `Business_Contract` | Passive | Соглашение провайдер–потребитель (права/обязанности, параметры) |
| Representation | `Business_Representation` | Passive | Воспринимаемая форма информации бизнес-объекта |
| Product | `Business_Product` | Composite | Согласованный набор сервисов/пассивных элементов + contract |
### 3.4. Application
| Элемент | Макрос | Аспект | Определение (N221) |
|---------|--------|--------|-------------------|
| Application Component | `Application_Component` | Active | Инкапсуляция прикладной функциональности, модульная и заменяемая |
| Application Collaboration | `Application_Collaboration` | Active | Агрегат ≥2 application internal active structure |
| Application Interface | `Application_Interface` | Active | Точка доступа к application services |
| Application Function | `Application_Function` | Behavior | Автоматизированное поведение компонента |
| Application Interaction | `Application_Interaction` | Behavior | Коллективное поведение ≥2 компонентов |
| Application Process | `Application_Process` | Behavior | Последовательность прикладного поведения к результату |
| Application Event | `Application_Event` | Behavior | Изменение состояния приложения |
| Application Service | `Application_Service` | Behavior | Явно определённое внешнее прикладное поведение |
| Data Object | `Application_DataObject` | Passive | Данные, структурированные для обработки |
### 3.5. Technology (+ Physical в гл. Technology 3.2)
| Элемент | Макрос | Определение (N221) |
|---------|--------|-------------------|
| Node | `Technology_Node` | Вычислительный/физический ресурс, хостящий другие ресурсы |
| Device | `Technology_Device` | Физический ИТ-ресурс для хранения/исполнения ПО и артефактов |
| System Software | `Technology_SystemSoftware` | ПО среды исполнения/хранения |
| Technology Collaboration | `Technology_Collaboration` | Агрегат ≥2 technology internal active structure |
| Technology Interface | `Technology_Interface` | Точка доступа к technology services |
| Path | `Technology_Path` | Связь между ≥2 technology internal active structure для обмена |
| Communication Network | `Technology_CommunicationNetwork` | Структуры/поведение для передачи данных |
| Technology Function | `Technology_Function` | Набор технологического поведения |
| Technology Process | `Technology_Process` | Последовательность технологического поведения |
| Technology Interaction | `Technology_Interaction` | Коллективное technology-поведение |
| Technology Event | `Technology_Event` | Изменение технологического состояния |
| Technology Service | `Technology_Service` | Явно определённое внешнее technology-поведение |
| Artifact | `Technology_Artifact` | Данные/файл, используемый или порождаемый разработкой/эксплуатацией |
| Equipment | `Physical_Equipment` | Физические машины/инструменты для материи |
| Facility | `Physical_Facility` | Физическая структура или окружение |
| Distribution Network | `Physical_DistributionNetwork` | Физическая сеть транспортировки материи/энергии |
| Material | `Physical_Material` | Осязаемая материя или энергия |
В 3.2 Device / System Software / Facility / Equipment — **не** подтипы Node, а technology internal active structure с composition/aggregation к Node (changelog C226).
### 3.6. Implementation & Migration
| Элемент | Макрос | Определение (N221) |
|---------|--------|-------------------|
| Work Package | `Implementation_WorkPackage` | Серия действий с результатом в сроках и ресурсах |
| Deliverable | `Implementation_Deliverable` | Точно определённый результат work package |
| Implementation Event | `Implementation_Event` | Изменение состояния, связанное с внедрением/миграцией |
| Plateau | `Implementation_Plateau` | Относительно стабильное состояние архитектуры на период |
| Gap | `Implementation_Gap` | Различие между двумя plateaus |
### 3.7. Composite и Junction
| Элемент | Макрос | Определение (N221) |
|---------|--------|-------------------|
| Grouping | `Grouping` / `Other_Grouping` / `Group` | Агрегирует/композирует концепты по общему признаку |
| Location | `Other_Location` / `Business_Location` | Место, где расположены или выполняются концепты |
| And Junction | `Junction_And` | Логическое И для связей одного типа |
| Or Junction | `Junction_Or` | Логическое ИЛИ для связей одного типа |
Grouping и Junction допустимы **в любом** viewpoint (спецификация).
### 3.8. Когда какой элемент поведения
| Нужно | Берите |
|-------|--------|
| Последовательность шагов к результату | `*_Process` |
| Группа поведения «изнутри» по компетенциям/ресурсам | `*_Function` |
| Поведение коллаборации (≥2 участников) | `*_Interaction` |
| Внешне видимое поведение (чёрный ящик) | `*_Service` |
| Момент / смена состояния | `*_Event` |
**Не смешивайте слои:** `Business_Process` ≠ `Application_Process` ≠ `Technology_Process`. Слой задаётся типом элемента, не подписью.
---
## 4. Связи
### 4.1. Одиннадцать типов (N221) + PlantUML
| Тип | Класс | Смысл (N221) | Макрос | Нотация PlantUML |
|-----|-------|--------------|--------|------------------|
| Composition | Structural | Элемент **состоит из** других; часть не существует без целого | `Rel_Composition` | `*--` |
| Aggregation | Structural | Элемент **объединяет** другие; части могут жить отдельно | `Rel_Aggregation` | `o--` |
| Assignment | Structural | Ответственность / выполнение поведения / хранение / исполнение | `Rel_Assignment` | `@-->>` |
| Realization | Structural | Критическая роль в создании/достижении более абстрактного | `Rel_Realization` | `~~|>` |
| Serving | Dependency | Предоставляет функциональность другому | `Rel_Serving` | `-->` |
| Access | Dependency | Поведение/active structure наблюдает или действует на passive | `Rel_Access` / `_r` / `_w` / `_rw` | `~~` / `<-~` / `~->` / `<~~>` |
| Influence | Dependency | Влияет на реализацию/достижение motivation-элемента (`+/-`) | `Rel_Influence` | `..>` |
| Triggering | Dynamic | Временная/причинная активация | `Rel_Triggering` | `-->>` |
| Flow | Dynamic | Передача чего-либо | `Rel_Flow` | `..>>` |
| Specialization | Other | Является разновидностью | `Rel_Specialization` | `--|>` |
| Association | Other | Неспецифичная связь (или нет другого типа) | `Rel_Association` / `_dir` | `--` / `--\` |
| Junction | Connector | Соединяет связи **одного** типа | `Junction_And` / `Junction_Or` | circle |
Направление на схеме: `Rel_Type_Up` / `_Down` / `_Left` / `_Right` (например `Rel_Serving_Up(svc, proc)`).
### 4.2. Направления (частые ошибки)
| Связь | Откуда → куда |
|-------|----------------|
| **Serving** | Поставщик (часто Service) → **потребитель** |
| **Realization** | Более конкретное → более абстрактное |
| **Composition / Aggregation** | Целое → часть |
| **Assignment** | Active structure → behavior (или ресурс хранения → artifact) |
| **Access** | Behavior (или active) → **passive**; тип: read / write / read-write |
| **Triggering** | Предшественник → следующий |
| **Flow** | Источник передачи → приёмник |
| **Influence** | Влияющий → motivation-элемент (сила `++`/`+`/`0`/`-`/`--` в подписи) |
| **Specialization** | Специализация → общий тип |
На листах: realization — «вверх» по абстракции; serving — к тому, кого обслуживают. Access всегда к объекту, независимо от отрисовки стрелки.
### 4.3. Правила с листов (метамодель ядра)
- Любой элемент может **compose/aggregate** элементы **того же класса** (на обзорных диаграммах часто не рисуют).
- Внутренние поведения одного слоя могут compose/aggregate друг друга (Function агрегирует Process).
- **Association** формально возможна между любыми классами — но на схеме используйте её только когда нет более точного типа.
- Collaboration ведёт себя как соответствующий internal active structure.
- Stakeholder — Association с любым элементом; элементы мотивации (кроме Stakeholder) — Influence друг на друга.
### 4.4. Чего нет в корпусе
Полная **Appendix B** (матрица всех допустимых пар и derivation) в sample PDF **обрезана**. Ниже — практические цепочки из §3.3, N221, листов и типичных viewpoint’ов. Не выдавайте их за полную нормативную матрицу B.
---
## 5. Что с чем связывать
### 5.1. Канонические цепочки
```text
# Внутри слоя
Business_Actor/Role Rel_Assignment Business_Process/Function
Business_Process Rel_Realization Business_Service
Business_Process Rel_Access_* Business_Object
Business_Event Rel_Triggering Business_Process
Application_Component Rel_Assignment Application_Function/Process
Application_Function Rel_Realization Application_Service
Application_Service Rel_Serving Business_Process/Role
Application_Component Rel_Access_* Application_DataObject
Application_Component Rel_Composition Application_Component
Technology_Node Rel_Composition Technology_Device / SystemSoftware
Technology_* Rel_Assignment Technology_Function/Process
Technology_Function Rel_Realization Technology_Service
Technology_Service Rel_Serving Application_Component
Technology_Artifact Rel_Realization Application_DataObject
Application_DataObject Rel_Realization Business_Object
# Стратегия / мотивация
Business_Process / Application_Service Rel_Realization Strategy_Capability
Application_Service / Component Rel_Realization Motivation_Requirement
Motivation_Driver Rel_Association Motivation_Stakeholder
Motivation_Assessment Rel_Association Motivation_Driver
Motivation_Goal Rel_Realization Motivation_Outcome
Motivation_Requirement Rel_Specialization Motivation_Constraint # или наоборот по смыслу «ограничение как вид требования» — лучше Constraint отдельно + Influence/Association
# Миграция
Implementation_WorkPackage Rel_Realization / Aggregation Implementation_Deliverable
Implementation_Plateau Rel_Aggregation core elements
Implementation_Gap Rel_Association between plateaus
```
### 5.2. Запреты для генерации
1. Не `Rel_Assignment` от Data Object / Business Object к процессу.
2. Не `Rel_Realization` от Component сразу к Process — нужен Function/Process того же слоя, затем Realization к Service.
3. Не `Rel_Serving` «потребитель → сервис» (перевёрнуто).
4. Не подменять Access потоком Flow «потому что данные».
5. Не рисовать `Business_Process` вместо `Application_Process`, если исполнитель — компонент.
6. Не ставить Association на все рёбра «на всякий случай».
7. Не считать Device подтипом Node без composition/aggregation (3.2).
---
## 6. Viewpoints
**Один рисунок = один viewpoint.** Не сваливайте мотивацию, бизнес, приложения и ЦОД на один холст без нужды (Layered — исключение, но всё равно ограничивайте число элементов).
Имена — из оглавления sample C226, Appendix C:
### 6.1. Basic (C.1)
| Viewpoint | Фокус | Типичные элементы |
|-----------|-------|-------------------|
| Organization | Структура орг. единиц | Actor, Role, Collaboration, Location, Interface |
| Application Structure | Внутренняя структура приложений | Component, Collaboration, Interface, Data Object |
| Information Structure | Данные/информация | Business Object, Representation, Data Object, Artifact, Meaning |
| Technology | Инфраструктура | Node, Device, System Software, Network, Path, Artifact… |
| Layered | Обзор слоёв | Набор из Business + Application + Technology + serving/realization |
| Physical | Физический мир | Equipment, Facility, Distribution Network, Material + tech |
| Product | Ценность продукта | Product, Contract, Services, Interfaces |
| Application Usage | Приложения в бизнес-контексте | Process/Function/Service бизнес + application |
| Technology Usage | Технологии для приложений | Application + Technology services/nodes |
| Business Process Cooperation | Связь процессов | Processes, Events, Services, Roles, supporting apps |
| Application Cooperation | Связь приложений | Components, Services, Interfaces, Data, Flow/Serving |
| Service Realization | Как сервисы реализованы | Service ← Process/Function ← Active structure |
| Implementation and Deployment | Развёртывание | Application + Artifact + Node/Device |
### 6.2. Motivation (C.2)
Stakeholder · Goal Realization · Requirements Realization · Motivation — Driver/Assessment/Goal/Outcome/Principle/Requirement/Constraint/Value/Meaning и Realization/Influence к core.
### 6.3. Strategy (C.3)
Strategy · Capability Map · Value Stream · Outcome Realization · Resource Map.
### 6.4. Implementation & Migration (C.4)
Project · Migration · Implementation and Migration — Work Package, Deliverable, Plateau, Gap, Event.
### 6.5. Макет
- Организация / структура: `LAYOUT_TOP_DOWN()` или вложенность `{ }`.
- Процессы слева направо: `LAYOUT_LEFT_RIGHT()` + `Rel_*_Right`.
- Layered: бизнес сверху, technology снизу; serving вверх (`Rel_Serving_Up`), realization вверх к абстракции.
- Широкие схемы: `%id … +landscape`.
Пример композиции (van den Berg): сначала **Motivation viewpoint** (риски/цели), затем отдельные схемы процессов с **Junction** на ветвлениях восстановления.
---
## 7. Синтаксис PlantUML
Документация: [plantuml.com/archimate-diagram](https://plantuml.com/archimate-diagram). Stdlib: Archimate-PlantUML **3.2.1**.
### 7.1. Рекомендуемый путь (схема md2gost)
```text
LAYOUT_TOP_DOWN() ' или LAYOUT_LEFT_RIGHT()
Business_Actor(a, "Имя")
Application_Service(s, "Сервис")
Rel_Serving_Up(s, a)
```
Include и `@startuml` добавляет схема `archimate`.
### 7.2. Низкоуровневый keyword (без макросов)
Только в `` ```uml ``, если stdlib недоступен:
```plantuml
@startuml
archimate #Business "Подача заявки" as p <<business-process>>
archimate #Application "Портал" as c <<application-component>>
c --> p
@enduml
```
Sprites: `<<$archimate/business-process>>` или `jar:archimate/...`.
**Не смешивайте** макросы и сырой `archimate` на одной схеме.
### 7.3. Темы
```plantuml
!theme archimate-standard from <archimate/themes>
' archimate-alternate | saturated | lowsaturation | handwriting
```
### 7.4. Nesting и special shapes
```plantuml
Business_Product(prod, "Тариф") {
Business_Service(s1, "Подключение")
Business_Contract(c1, "Оферта")
}
```
Для special shapes (`$ARCH_SPECIAL_SHAPES`) у Service/Actor/Value/ValueStream при вложении: `$nest=%true()`.
### 7.5. Layout helpers
`Lay_U` / `Lay_D` / `Lay_L` / `Lay_R` — скрытые связи для выравнивания.
`LAYOUT_AS_SKETCH()` — черновик (не для финального ГОСТ-рисунка).
### 7.6. Sequence с ArchiMate
Только если явно просят sequence: `!global $ARCH_SEQUENCE_SUPPORT = %true()` до include. Это **не** замена viewpoint.
### 7.7. List sprites
```plantuml
@startuml
listsprite
@enduml
```
---
## 8. Чеклист для ИИ
1. Версия языка: **ArchiMate 3.2**; макросы слоя (`Business_*`, `Application_*`, …).
2. Оградка `` ```uml-archimate ``; без `@startuml` / `!include`.
3. Выбрать **один** viewpoint; 8–18 элементов на рисунок.
4. Сначала все элементы, потом все `Rel_*`.
5. Alias латиницей; подписи по-русски в кавычках; длинные имена с `\n`.
6. Serving от сервиса к потребителю; Realization от конкретного к абстрактному.
7. Поведение того же слоя, что и исполнитель (Assignment).
8. Не UML class/component, не C4 `Person`, не BPMN `XOR`, не mxgraph.
9. Не Association «по умолчанию».
10. Для отчёта: `%id Название` (+ `+landscape` если широко).
---
## 9. Готовые шаблоны
Тела для `` ```uml-archimate `` (без обёртки).
### 9.1. Organization
```plantuml
LAYOUT_TOP_DOWN()
Business_Actor(uni, "Университет") {
Business_Actor(dean, "Деканат")
Business_Actor(it, "Управление ИТ")
}
Business_Role(student, "Студент")
Business_Role(clerk, "Методист")
Rel_Assignment(dean, clerk)
Rel_Assignment(uni, student)
```
### 9.2. Service Realization
```plantuml
LAYOUT_TOP_DOWN()
Business_Role(applicant, "Абитуриент")
Business_Process(apply, "Подача заявления")
Business_Service(applySvc, "Приём заявлений")
Application_Service(webSvc, "Веб-приёмная")
Application_Component(lk, "Личный кабинет")
Application_Function(submitFn, "Отправка формы")
Rel_Assignment(applicant, apply)
Rel_Realization(apply, applySvc)
Rel_Serving(webSvc, apply)
Rel_Assignment(lk, submitFn)
Rel_Realization(submitFn, webSvc)
```
### 9.3. Application Cooperation
```plantuml
LAYOUT_LEFT_RIGHT()
Application_Component(crm, "CRM")
Application_Component(billing, "Биллинг")
Application_Service(crmApi, "API клиентов")
Application_DataObject(client, "Карточка клиента")
Rel_Realization(crm, crmApi)
Rel_Serving(crmApi, billing)
Rel_Access_rw(crm, client)
Rel_Access_r(billing, client)
Rel_Flow(crm, billing, "событие оплаты")
```
### 9.4. Layered
```plantuml
LAYOUT_TOP_DOWN()
Business_Process(sale, "Оформление заказа")
Business_Object(order, "Заказ")
Application_Service(shopSvc, "Интернет-магазин")
Application_Component(shop, "ShopApp")
Technology_Service(dbSvc, "СУБД")
Technology_Node(dbHost, "DB Host")
Technology_SystemSoftware(pg, "PostgreSQL")
Rel_Access_w(sale, order)
Rel_Serving_Up(shopSvc, sale)
Rel_Realization(shop, shopSvc)
Rel_Serving_Up(dbSvc, shop)
Rel_Assignment(dbHost, dbSvc)
Rel_Composition(dbHost, pg)
```
### 9.5. Motivation / Requirements Realization
```plantuml
LAYOUT_TOP_DOWN()
Motivation_Stakeholder(rector, "Ректор")
Motivation_Driver(comp, "Конкуренция вузов")
Motivation_Goal(digital, "Цифровизация приёма")
Motivation_Requirement(online, "Заявление онлайн 24/7")
Motivation_Constraint(152fz, "152-ФЗ")
Application_Service(portal, "Портал абитуриента")
Rel_Association(rector, comp)
Rel_Association(comp, digital)
Rel_Realization(online, digital)
Rel_Influence(152fz, online, "-")
Rel_Realization(portal, online)
```
### 9.6. Implementation & Migration
```plantuml
LAYOUT_LEFT_RIGHT()
Implementation_Plateau(asIs, "AS-IS 2025")
Implementation_Plateau(toBe, "TO-BE 2026")
Implementation_Gap(gap1, "Нет единого ЛК")
Implementation_WorkPackage(wp, "Проект Единый ЛК")
Implementation_Deliverable(d1, "Релиз 1.0")
Implementation_Event(goLive, "Go-Live")
Rel_Association(gap1, asIs)
Rel_Association(gap1, toBe)
Rel_Realization(wp, d1)
Rel_Triggering(d1, goLive)
Rel_Triggering(goLive, toBe)
```
### 9.7. Technology Usage
```plantuml
LAYOUT_TOP_DOWN()
Application_Component(api, "API Gateway")
Technology_Node(k8s, "Kubernetes")
Technology_Device(node1, "Worker x86")
Technology_SystemSoftware(os, "Linux")
Technology_CommunicationNetwork(net, "Cluster CNI")
Technology_Artifact(image, "api:1.2.img")
Rel_Serving_Up(k8s, api)
Rel_Composition(k8s, node1)
Rel_Composition(node1, os)
Rel_Association(node1, net)
Rel_Assignment(node1, image)
```
### 9.8. Process с Junction (в духе van den Berg)
```plantuml
LAYOUT_LEFT_RIGHT()
Business_Event(incident, "Инцидент")
Business_Process(triage, "Триаж")
Junction_Or(j1, "")
Business_Process(restore, "Восстановление КФ")
Business_Process(investigate, "Расследование")
Business_Process(close, "Закрытие")
Rel_Triggering(incident, triage)
Rel_Triggering(triage, j1)
Rel_Triggering(j1, restore)
Rel_Triggering(j1, investigate)
Rel_Triggering(restore, close)
Rel_Triggering(investigate, close)
```
---
## 10. Антипаттерны
| Плохо | Почему | Как надо |
|-------|--------|----------|
| Все связи `Rel_Association` | Теряется семантика | Serving / Realization / Assignment / Access |
| `Application_Component` вместо `Business_Actor` | Разные аспекты и слои | Actor/Role для людей/орг. единиц |
| Business Process «внутри» компонента без Assignment | Слои смешаны | Process на бизнес-слое; Serving от Application Service |
| Serving от Role к Service | Направление наоборот | Service → Role/Process |
| Realization Component → Process | Пропущен внутренний behavior | Component → Function → Service |
| Flow вместо Access к Data Object | Flow — передача, Access — работа с объектом | `Rel_Access_r/w/rw` |
| Один Layered на 40+ элементов | Нечитаемо | Несколько viewpoint’ов |
| C4 `Person` / UML class в archimate-блоке | Другой язык | Только макросы ArchiMate |
| Generic «Process» без слоя | В 3.2 слоя обязательны | `Business_Process` / `Application_Process` / … |
---
## 11. Источники и границы корпуса
### Норматив (при конфликте — сверху вниз)
1. **n221p.pdf** — ArchiMate 3.2 Reference Cards (N221): определения элементов и связей.
2. **978940180955C_SMPL.pdf** (+ дубль SMPL-1) — sample C226: гл. 12, начало гл. 3, оглавление (в т.ч. список viewpoints Appendix C).
3. **archimate-sheets-ru-20230805-s.pdf** — листы метамодели 3.2 (Виерда / Ефремов): прямые связи, цвета аспектов на листах. Описания элементов на листах **не** от Open Group — для формулировок «что такое X» побеждает N221.
### Синтаксис рисунка
- [plantuml.com/archimate-diagram](https://plantuml.com/archimate-diagram)
- Stdlib Archimate-PlantUML 3.2.1 (`!include <archimate/Archimate>`)
### Примеры композиции (не словарь языка)
- hospital ZiRA preview (inkijkexemplaar) — reference architecture / C226.
- **vandenBerg_MA_EEMCS.pdf** — §2.4 framework, motivational viewpoint, Junction в процессах BCM/DR.
### Не правила ArchiMate
- Article_37 (FEM), paper_41 (OntoUML/COVO), FASD (UML атак), 419 (единое окно), **2659430** (Packt Practical Cybersecurity Architecture — процесс кибер-архитектуры, не спецификация 3.2).
### Ограничения
- Полная Appendix B в sample отсутствует — матрица пар здесь практическая, не нормативная таблица B.5.
- PDF спецификации в git не хранятся.
- Старый PlantUML/Kroki без stdlib 3.2: fallback — `` ```uml `` + keyword `archimate`.
- Пользовательский `md2gost.schemes.json`: встроенные схемы с `author: md2gost` синхронизируются с бандлом; свои правки (другой author) не затираются.
---
См. также: [schemes.md](schemes.md), меню **Шаблоны UML**, **Справка → Промпт для ИИ** (схема `archimate`).
-84
View File
@@ -1,84 +0,0 @@
# CLI и GUI
Движок один: GUI собирает те же параметры, что и аргументы `python -m md2gost`.
## Основные команды
```bash
python -m md2gost # GUI
python -m md2gost --gui report.md
python -m md2gost report.md -o out.docx --type coursework --check --strict
python -m md2gost report.docx -o report.md # импорт Word → Markdown (word2md)
python -m md2gost report.docx --check-pages # только проверка вёрстки готового DOCX
python -m word2md report.docx -o report.md
```
Справка: `python -m md2gost -h`.
## Соответствие флагов и GUI
| CLI | Где в GUI | Смысл |
|-----|-----------|--------|
| `--type` | Основные → тип | practice, coursework, vkr, PIS_custom, APID_coursework |
| `-o` / `--output` | Выходной DOCX | путь результата |
| `--heading-numbering` | Основные | `manual` (цифры в md) / `auto` (Word) |
| `--toc` | Основные | `native` (поле Word) / `manual` (собирает md2gost) |
| `--emdash-to-hyphen` | Галочка «—» → «-» | по умолчанию выкл. |
| `--hr-pagebreak` | Галочка --- → разрыв | по умолчанию `---` игнорируется |
| `--title` / `--assignment` / `-t` | Настройки → Файлы | титул, задание, шаблон |
| `--auto-title` / `--no-auto-title` | галочка «Автотитул» | автогенерация титула (по умолчанию выкл.) |
| `--student` / `--group` | Настройки → Студент… | ФИО и группа для автотитула |
| `--doc-author-from` / `--doc-author` | Настройки → Метаданные… | автор в свойствах DOCX (`os` / `student` / `custom`) |
| `--doc-title` / `--doc-subject` / `--doc-keywords` / `--doc-comments` / `--doc-category` / `--doc-last-modified-by` | Настройки → Метаданные… | остальные поля File → сведения |
| `--check` / `--check-only` / `--strict` | Галочки проверки ТЗ | замечания по структуре и источникам |
| `--check-pages` | Проверить вёрстку в Word | эвристика полупустых страниц (Word + pywin32) |
| `--table-continuation` | Основные | `word` (по умолчанию), `off`, `legacy`, `caption`, `soft` |
| `--listing-continuation` | Основные | то же для листингов |
| `--table-repeat-header` | Галочка | шапка на фрагментах после word-split |
| `--plantuml-jar` / `--kroki-url` | Настройки → Диаграммы | локальный рендер UML / запасной Kroki |
| `--diagram-fallback` | Диаграммы | `remote` / `local` / `off` (отключает только kroki.io) |
| `--diagram-format` | Диаграммы | `png` / `svg` |
| `--diagram-scale` | Диаграммы | качество PNG PlantUML / локального Mermaid (по умолчанию 2) |
| `--page-start N` | Основные → Смещение страниц | начальный номер PAGE в теле; пусто = сквозной |
| (нет CLI) | Диаграммы → «Скачать Graphviz» | portable Graphviz для DFD (`vendor` или `%LOCALAPPDATA%\md2gost\graphviz`) |
| `--install-chromium` | Диаграммы → «Скачать headless Chromium» | Chromium для Mermaid в `%LOCALAPPDATA%\md2gost` |
| `--schemes` | файл схем / Шаблоны UML | путь к `md2gost.schemes.json` |
| `--styles` | Настройки → Файлы → Стили JSON | оверлей `md2gost.styles.json` (также рядом с `.md`); см. [styles.md](styles.md) |
| `--syntax-highlighting` | (CLI) | подсветка в листингах |
| `--debug` | меню Дебаг | отладочные данные в документе (на одну сборку в GUI) |
## Продолжение таблиц и листингов
DOCX не умеет сам писать «Продолжение Таблицы N» только со 2-й страницы. Режим **`word`** (по умолчанию): после сохранения Word COM режет по реальной пагинации. Нужны Windows + Word + pywin32. Без Word: `--table-continuation off` (и то же для листингов).
## Меню GUI
- **Настройки → Файлы** — шаблон, титул, задание, стили JSON, выходной путь
- **Настройки → Студент…** — ФИО и группа (при первом запуске спрашивают сами)
- **Настройки → Метаданные…** — свойства DOCX (автор, название, тема, теги, примечание)
- **Настройки → Диаграммы** — PlantUML, Graphviz (DFD), Mermaid (Chromium), Kroki, формат, кэш includes
- **Шаблоны UML** — редактор `md2gost.schemes.json`
- **Справка → Инструкция / Документация / Схемы / Промпт для ИИ**
(Документация — встроенный просмотр `docs/*.md`, вшито в exe)
## Автотитульник
Кратко: **по умолчанию выкл.** Вкл. — `--auto-title` или галочка «Автотитул». Рядом с `.md``info_conv.yaml`, в MD — опциональный блок `title` (`number` / `year`), ФИО и группа — **Настройки → Студент…** или `--student` / `--group`. Явный `--title` отключает генератор.
Подробно (примеры, таблица полей, приоритеты, FAQ): **[title.md](title.md)**.
## Свойства файла Word
По умолчанию в DOCX пишутся **автор = имя пользователя Windows** и примечание «Создано при помощи md2gost (ТЗ МИРЭА)». Даты создания/изменения ставятся на момент сборки, revision = 1 (чтобы не утекали 2013 год и revision из шаблона).
Задать свои поля: **Настройки → Метаданные…** (сохраняется в `md2gost.user.json`) или флаги `--doc-author-from` / `--doc-author` / `--doc-title` / `--doc-subject` / `--doc-keywords` / `--doc-comments` / `--doc-category` / `--doc-last-modified-by`. Источник автора: `os` (по умолчанию), `student` (ФИО из профиля), `custom` (строка). Пустое `--doc-comments` / пустое примечание в GUI — не писать штамп md2gost.
## Другие форматы
```bash
python -m md2fodt report.md -o report.fodt # LibreOffice
python -m word2md report.docx -o report.md # Word → Markdown (диалект md2gost)
# PDF через LaTeX — см. md2latex/
```
Импорт DOCX подробнее: [word2md.md](word2md.md). В GUI — кнопка «Импорт DOCX→MD» или drop `.docx`.
-159
View File
@@ -1,159 +0,0 @@
# Синтаксис Markdown (диалект md2gost)
Обычный Markdown описывает структуру текста. Для отчёта по ГОСТ нужны ещё: спецразделы без номера, подписи объектов, перекрёстные ссылки, библиография в заданном виде. **md2gost** расширяет MD ровно этими элементами; конвертер сам нумерует рисунки/таблицы/листинги и оформляет DOCX.
## Что совпадает с обычным MD
- Заголовки `#``######`
- Абзацы, **жирный**, *курсив*
- Маркированные и нумерованные списки
- Таблицы `| … |`
- Картинки `![alt](path.png)`
- Блоки кода в ограде ` ```язык `
- Формулы `$$ … $$` (и инлайн `$…$` где поддерживается)
## Зачем расширения
| Задача | Обычный MD | md2gost |
|--------|------------|---------|
| Введение без номера «1» | `# Введение` → станет разделом 1 | `# *ВВЕДЕНИЕ` |
| Подпись «Рисунок 1.1 — …» | руками / HTML | `%id` или title у картинки |
| «см. рис. 2» в тексте | нет семантики | `@Рисунок:id` |
| UML → картинка в Word | экспорт PNG вручную | fence `` ```uml `` / схема → Рисунок |
## Спецразделы
Звёздочка `*` = без автоматической нумерации раздела. Текст — ПРОПИСНЫМИ:
```markdown
# *СОДЕРЖАНИЕ
[TOC]
# *ВВЕДЕНИЕ
# 1 Название первого раздела
## 1.1 Подраздел
# *ЗАКЛЮЧЕНИЕ
# *СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
# *ПРИЛОЖЕНИЯ
```
- После `# *СОДЕРЖАНИЕ` обязателен `[TOC]`.
- В конце названия заголовка точку не ставить.
- Для `PIS_custom` структура другая (практические работы) — см. [types.md](types.md).
## Рисунок (файл)
```markdown
Текст со ссылкой на @Рисунок:arch.
![описание](images/arch.png "%arch Название рисунка")
```
В тексте пишите **«Рисунок»**, не «рис.» / «рис».
## Таблица
```markdown
См. @Таблица:cmp.
%cmp Название таблицы
| A | B |
|---|---|
| 1 | 2 |
```
Склеивание ячеек:
- `^` — rowspan (продолжение ячейки сверху)
- `>` — colspan (продолжение слева)
Не ставить `^`/`>` в заголовочной строке; `>` — не в первом столбце. Графу «№ п/п» не добавлять.
## Листинг
~~~markdown
Фрагмент в @Листинг:code1.
%code1 Название листинга
```python
def f():
return 1
```
~~~
## Диаграмма → Рисунок
Перед блоком — `%id Подпись`. Языки: `uml`, `plantuml`, `mermaid`/`mmd`, `idef0`, `dfd`/`data-flow-diagram` (Graphviz вшитый/PATH или Kroki), или id схемы (`c4`, `usecase`, …).
- `+listing` — ещё и Листинг с исходником
- `+landscape` — альбомная страница под широкий рисунок/таблицу
Подробности: [schemes.md](schemes.md).
## Формула
```markdown
%eq1
$$
E = mc^2
$$
Зависимость (@Формула:eq1) используется далее.
```
Нумеруются **только** формулы, на которые есть `@Формула:`.
## Ссылки на объекты
`@Рисунок:id`, `@Таблица:id`, `@Листинг:id`, `@Формула:id` — id совпадает с меткой после `%` или в title картинки.
## Источники
В тексте: `[1]`, `[2, 3]` (для ВКР — `[1.5]`). В DOCX номера становятся ссылками на пункты списка источников.
В списке:
```markdown
[1]: Иванов И. И. Название. — М.: Наука, 2024. — 120 с.
```
Во **ВВЕДЕНИИ** и **ЗАКЛЮЧЕНИИ** ссылок `[n]` быть не должно.
## Приложения
```markdown
# *ПРИЛОЖЕНИЯ
## Приложение А Листинг модуля
## Приложение Б Графический материал
```
Буквы: А, Б, В, Г, Д, Е, Ж, И, К… **Нельзя:** Ё, З, Й, О, Ч, Ь, Ы, Ъ.
## Тире и разрыв страницы
- Тире в предложениях: «—» (по умолчанию сохраняется). Замена на «-»: `--emdash-to-hyphen`.
- Строка `---` / `***` / `___` по умолчанию **игнорируется**. Разрыв страницы: `--hr-pagebreak` или галочка в GUI.
## Автотитульник (метаданные в MD)
В начале файла можно указать блок с оградой `title` (номер работы, год, оверрайды полей). Рядом с файлом — `info_conv.yaml` с институтом, кафедрой, дисциплиной и преподавателем. ФИО и группа студента задаются в GUI / CLI, не в yaml. Автогенерация титула **по умолчанию выкл.** — включите `--auto-title` или галочку «Автотитул».
Подробно: [title.md](title.md).
## Запрещено в отчёте
- «рис.», «табл.»
- графа «№ п/п»
- сноски `[^1]`
- формулы обычным текстом вместо `$$…$$`
- нумерация спецразделов (`# ВВЕДЕНИЕ` вместо `# *ВВЕДЕНИЕ`)
-34
View File
@@ -1,34 +0,0 @@
# Промпты для ИИ
Промпты лежат в [`prompts/`](../prompts/). В GUI: **Справка → Промпт для ИИ** — выбрать, при необходимости **дописать схемы**, скопировать в буфер. Полная документация также доступна в **Справка → Документация** (вшита в exe).
## Какие файлы
| Файл | Когда |
|------|--------|
| [`generate-md.md`](../prompts/generate-md.md) | Базовый: диалект md2gost, чем отличается от обычного MD; UML/Mermaid рисует конвертер |
| [`generate-mirea-report.md`](../prompts/generate-mirea-report.md) | Полный отчёт ГОСТ / МИРЭА (`coursework`, `practice`, `vkr`) |
| [`generate-pis-custom-report.md`](../prompts/generate-pis-custom-report.md) | Итоговый отчёт ПИС (`PIS_custom`) |
| [`emulate-student.md`](../prompts/emulate-student.md) | После любого generate-*: текст про предмет, не отчёт модели о сдаче ТЗ |
## Как пользоваться
1. Откройте промпт (файл или GUI). При необходимости добавьте `emulate-student` после базового generate-*.
2. В GUI включите нужные схемы (C4, usecase, …) — в конец промпта добавятся макросы и `ai-prompt` из `md2gost.schemes.json`.
3. Скопируйте собранный текст в ChatGPT / Claude / Cursor / Copilot.
4. Следующим сообщением: тип работы, тема, черновик / требования.
5. Сохраните ответ как `.md` и конвертируйте:
```bash
python -m md2gost report.md -o report.docx --type coursework --check --strict
```
## Зачем кнопки схем
Базовый промпт уже говорит: блоки `` ```uml `` / `` ```mermaid `` / `` ```uml-c4 `` конвертер сам превратит в Рисунок. Кнопки нужны, когда модели надо знать **конкретные макросы** выбранной схемы (Person/Rel для C4, actor/usecase и т.д.) — в том числе пользовательских из «Шаблоны UML».
## Подробнее о синтаксисе
- [markdown.md](markdown.md)
- [schemes.md](schemes.md)
- [prompts/README.md](../prompts/README.md)
-64
View File
@@ -1,64 +0,0 @@
# Быстрый старт
## Установка
Нужен Python 3.10+.
```bash
pip install -e .
# или
poetry install
```
Для продолжения таблиц/листингов через Word COM (режим `word` по умолчанию) на Windows:
```bash
pip install pywin32
```
Нужны установленный Microsoft Word.
## Запуск
```bash
python -m md2gost # GUI без файла
python -m md2gost --gui
python -m md2gost report.md -o report.docx --type coursework --check
md2gost-gui # то же GUI (entry point)
```
### Windows exe
В корне репозитория: `build-exe.bat``dist\md2gost.exe`.
- Двойной клик — GUI.
- CLI: `md2gost.exe report.md -o report.docx --type coursework`.
## GUI за минуту
1. Перетащите `.md` в верхнюю область (или кликните по ней).
2. Выберите тип документа (`practice` по умолчанию).
3. При необходимости: Настройки → Файлы (титул, задание), **Настройки → Студент…** (ФИО и группа для автотитула), **Настройки → Метаданные…** (свойства DOCX), Настройки → Диаграммы, меню «Шаблоны UML».
4. Нажмите «Конвертировать».
Справка в меню: **Инструкция**, **Схемы**, **Промпт для ИИ**.
Автотитул (`info_conv.yaml` + блок `title`): [title.md](title.md).
## Типы документов (кратко)
| `--type` | Назначение |
|----------|------------|
| `practice` / `coursework` | Практика / курсовая по ТЗ МИРЭА |
| `vkr` | ВКР (раздельный список, графическое приложение) |
| `PIS_custom` | Итоговый отчёт по практическим работам |
| `APID_coursework` | Курсовая «Архитектура приложений и данных» |
Подробнее: [types.md](types.md).
## Следующие шаги
- Написать отчёт в диалекте md2gost: [markdown.md](markdown.md)
- Автотитульник: [title.md](title.md)
- Вставить диаграммы: [schemes.md](schemes.md)
- Сгенерировать `.md` через ИИ: [prompts.md](prompts.md)
-272
View File
@@ -1,272 +0,0 @@
# Схемы и диаграммы
В отчёте блок кода с языком диаграммы превращается в **Рисунок** (PNG или SVG). PNG руками экспортировать не нужно: md2gost вызывает PlantUML (jar / Kroki), локальный Mermaid (браузер / QuickJS), локальный IDEF0 (Pillow) или DFD через [data-flow-diagram](https://github.com/pbauermeister/dfd) (вшитый / системный Graphviz или Kroki).
## Синтаксис в markdown
````markdown
%usecase1 Диаграмма прецедентов +listing
```uml
@startuml
actor Student
Student --> (Login)
@enduml
```
````
Широкая схема:
````markdown
%arch1 Архитектура +landscape
```uml-c4
Person(user, "Студент")
System(app, "Портал")
Rel(user, app, "логин")
```
````
| Оградка | Что происходит |
|---------|----------------|
| `` ```uml `` / `` ```plantuml `` | Сырой PlantUML (`@startuml`…`@enduml`) |
| `` ```uml-<id> `` / `` ```<id> `` | Схема из `md2gost.schemes.json` (обёртка и `!include` добавляются сами) |
| `` ```mermaid `` / `` ```mmd `` | Mermaid: браузер / QuickJS / Kroki |
| `` ```idef0 `` / `` ```uml-idef0 `` | IDEF0 (FIPS 183): локальный рендер, без PlantUML / Kroki |
| `` ```dfd `` / `` ```uml-dfd `` / `` ```data-flow-diagram `` | DFD ([pbauermeister/dfd](https://github.com/pbauermeister/dfd)): вшитый Graphviz / PATH / Kroki |
## Встроенные схемы
Файл шаблона: [`md2gost/diagrams/schemes.json`](../md2gost/diagrams/schemes.json). При первом запуске копируется в `md2gost.schemes.json` рядом с приложением. При каждом запуске встроенные схемы (`author: md2gost`) синхронизируются с шаблоном: новые id добавляются, устаревшие (например удалённый `bpmn`) убираются, содержимое обновляется. Схемы с пустым или другим `author` не трогаются. Если правите встроенную в GUI и сохраняете — `author` сбрасывается, чтобы миграция не затёрла правки.
| id | Название | Оградка |
|----|----------|---------|
| `c4` | C4 Container | `` ```uml-c4 `` / `` ```c4 `` |
| `c4context` | C4 Context | `` ```uml-c4context `` |
| `c4component` | C4 Component | `` ```uml-c4component `` |
| `usecase` | Прецеденты | `` ```uml-usecase `` / `` ```usecase `` |
| `archimate` | ArchiMate 3.2 | `` ```uml-archimate `` / `` ```archimate `` |
Для схем в теле пишите **только макросы** (Person, Rel, actor, Business_Actor, …) — без `@startuml` и без `!include`, если схема сама их добавляет.
### C4 (пример макросов)
`Person`, `System`, `System_Ext`, `Container`, `ContainerDb`, `Rel` / `Rel_R`…
### Use Case
`actor`, `usecase`, связи `-->`, `<<include>>`, `<<extend>>`.
### ArchiMate 3.2
`Business_Actor`, `Application_Service`, `Technology_Node`, `Rel_Serving` / `Rel_Realization` / `Rel_Assignment`, …
Подробно: [archimate.md](archimate.md).
Полные шпаргалки — поля `docs` и `ai-prompt` в JSON; в GUI: **Шаблоны UML** и кнопки схем в **Справка → Промпт для ИИ**.
## IDEF0 (FIPS 183)
Оградка `` ```idef0 `` (то же: `` ```uml-idef0 ``). Текст — не XML: шапка формы, боксы, стрелки ICOM (Input слева, Control сверху, Output справа, Mechanism снизу). Контекст A-0 — один бокс; декомпозиция — несколько боксов «лесенкой» и связи между ними. Рендер локальный (Pillow), без Java и Kroki.
````markdown
%a0 Контекстная диаграмма A-0
```idef0
title Распорядиться товаром
node A-0
number 1
author Кинзябулатов Рамиль
project Разработка универсальной модели торгового предприятия
date 08.02.2022
rev 31.03.2022
status PUBLICATION
context TOP
[A0] Распорядиться товаром
<- Спрос
^ Нормативная документация
-> Товар
v Персонал
```
````
Шапка/подвал NIST-формы (необязательные поля): `title`, `node`, `number`, `author`, `project`, `date`, `rev`, `status` (`WORKING` / `DRAFT` / `RECOMMENDED` / `PUBLICATION`), `context` (для A-0 — `TOP`), `used_at`, `reader`, `reader_date`, `notes`, `purpose`, `viewpoint`, `page`, `form` (`kit` по умолчанию, `plain` — без рамки).
Бокс: `[A0] Имя` или `box A0 Имя`. Стрелки к последнему боксу: `<-` / `in` вход, `^` / `control` управление, `->` / `out` выход, `v` / `mech` механизм. Явно: `A0 <- Спрос`.
Декомпозиция A0 (3 бокса, развилка, O→C, ICOM на рамке):
````markdown
%a0 Декомпозиция A0
```idef0
title Распорядиться товаром
node A0
number 2
author Кинзябулатов Рамиль
project Разработка универсальной модели торгового предприятия
date 08.02.2022
rev 31.03.2022
status PUBLICATION
context A-0
purpose Обеспечить наличие товара и его отпуск покупателю
viewpoint Руководитель торгового предприятия
[A1] Принять и оценить спрос
[A2] Закупить и хранить
[A3] Отгрузить товар
A1 <- Спрос [I1]
A2 <- Предложения поставщиков [I2]
A1, A2, A3 ^ Нормативная документация [C1]
A1 ^ Ассортиментная политика [C2]
A3 ^ Условия поставки [C3]
A1 -> A2 : план закупок
A1 -> A2.C : график поставок
A2 -> A3 : товар к отгрузке
A3 -> Товар [O1]
A3 -> Акт отгрузки [O2]
A1, A2, A3 v Персонал [M1]
A2 v Склад [M2]
```
````
Подписи к стрелкам — существительные рядом со стволом, не на линии; если связь не очевидна, рисуется squiggle (FIPS 183). Длинные фразы переносятся на 2–3 строки.
Короткий каркас:
```
[A1] Принять заказ
[A2] Отгрузить
A1 <- Заявка [I1]
A1 ^ Правила [C1]
A1 -> A2 : заказ
A1 -> A2, A3 : данные
A1, A2 -> A3 : сводка
A2 -> Товар [O1]
A2 v Склад [M1]
```
Туннель (скобки IDEF0): `(in Секрет` — на границе листа, `in) Локальный` — у бокса. Вызов другой модели: `call ИмяМодели`. Сторона порта: `A1.O -> A2.C : условие`.
## DFD (data-flow-diagram / SA/RT)
Оградка `` ```dfd `` (то же: `` ```uml-dfd ``, `` ```data-flow-diagram ``, `` ```yourdon ``). Синтаксис — пакет [pbauermeister/dfd](https://github.com/pbauermeister/dfd) (ставится с md2gost, Python 3.11+). Рендер: Graphviz (`dot` / `neato`) или Kroki (`graphviz`), не Pillow.
Порядок поиска Graphviz (как у `plantuml.jar`):
1. Вшитый `md2gost/vendor/graphviz` (exe-сборка / `python scripts/fetch_graphviz.py`)
2. Кэш `%LOCALAPPDATA%\md2gost\graphviz` (GUI: **Настройки → Диаграммы → «Скачать Graphviz»**)
3. `dot` / `neato` в `PATH`
4. Локальный Kroki → `https://kroki.io` при `--diagram-fallback remote`
````markdown
%dfd0 Контекстная DFD
```dfd
style context
entity Client Клиент
entity Warehouse Склад
process System Система учёта заявок
Client --> System заявка
System --> Client статус
System --> Warehouse накладная
```
````
Ключевые слова узлов: `process`, `entity`, `store`, `control`, `channel`. Потоки: `-->`, `->>`, `<->`, сигналы `::>` / `<::`. Контекст: `style context`. Полный синтаксис — [документация Upstream](https://github.com/pbauermeister/dfd/blob/main/doc/README.md).
Декомпозиция (уровень 0):
````markdown
%dfd1 DFD уровня 0
```dfd
entity Client Клиент
entity Warehouse Склад
process Accept Принять заявку
process Register Зарегистрировать
process Ship Сформировать накладную
store Orders Заявки
Client --> Accept заявка
Accept --> Orders новая заявка
Orders --> Register данные заявки
Register --> Ship подтверждённая заявка
Ship --> Warehouse накладная
Ship --> Client уведомление
```
````
Зависимости: `data-flow-diagram` идёт с md2gost (Python ≥3.11). Без Graphviz офлайн DFD не нарисуется — либо кнопка «Скачать Graphviz» / `scripts/fetch_graphviz.py`, либо `--diagram-fallback remote` → kroki.io.
## Файл схем: поля
```json
{
"c4": {
"title": "C4 Container",
"docs": "…макросы…",
"ai-prompt": "…инструкция для ИИ…",
"includes": ["https://…/C4_Container.puml"],
"prefix": "@startuml\n",
"postfix": "\nLAYOUT_WITH_LEGEND()\n@enduml"
}
}
```
| Поле | Назначение |
|------|------------|
| `title` | Подпись в GUI |
| `docs` | Шпаргалка макросов |
| `ai-prompt` | Фрагмент для промпта ИИ |
| `includes` | Локальные `.puml` или URL |
| `prefix` / `postfix` | Обёртка вокруг тела |
| `theme` | опционально `!theme …` |
id схемы: латиница, цифры, `_`; начинается с буквы.
## Слои загрузки (позже побеждает)
1. Встроенный шаблон `md2gost/diagrams/schemes.json`
2. Пользовательский файл рядом с приложением (`md2gost.schemes.json`)
3. `md2gost.schemes.json` рядом с `.md`
4. Явный путь `--schemes path.json`
## Рендер
**UML / схемы:**
1. Java + `plantuml.jar` (вшитый / `%LOCALAPPDATA%\md2gost\` / `--plantuml-jar`)
2. Локальный Kroki (`KROKI_URL` / `--kroki-url`, по умолчанию `http://localhost:8000`)
3. `https://kroki.io` при `--diagram-fallback remote` (по умолчанию)
**Mermaid:**
1. Системный Chrome / Edge (через Playwright, ничего не качаем)
2. Playwright Chromium в `%LOCALAPPDATA%\md2gost\ms-playwright` — кнопка «Скачать headless Chromium» или `md2gost --install-chromium`
3. QuickJS + mermaid.js (`mermaidx`) — офлайн без браузера
4. Локальный Kroki → `https://kroki.io` (если `--diagram-fallback remote`)
**IDEF0:** сразу Pillow (PNG, при `--diagram-format svg` ещё SVG). Java/Kroki не используются.
**DFD:**
1. [data-flow-diagram](https://github.com/pbauermeister/dfd) компилирует DSL → DOT
2. Вшитый / кэш / PATH Graphviz (`dot`, для `style context``neato`)
3. Локальный Kroki → `https://kroki.io` при `--diagram-fallback remote`
Формат: `--diagram-format png` (по умолчанию) или `svg`. Масштаб растра PlantUML / локального Mermaid / IDEF0: `--diagram-scale` (по умолчанию 2 — качество, размер на странице как при 1).
Кэш картинок: `{каталог_md}/.md2gost-cache/`.
Кэш includes: `md2gost.include-cache.json` + папка `include-cache/` (сброс в GUI: Настройки → Диаграммы / Шаблоны UML).
## Свои схемы
1. Меню **Шаблоны UML** — добавить / править / сохранить.
2. Или править `md2gost.schemes.json` вручную («Открыть JSON»).
3. CLI: `--schemes путь.json`.
Чтобы правка встроенной схемы не сбрасывалась при обновлении приложения, оставьте пустой `author` (GUI делает это сама при сохранении изменённой встроенной схемы).
-67
View File
@@ -1,67 +0,0 @@
# Кастомные стили (JSON)
Опциональный оверлей оформления поверх пресета `--type` (`mirea` или `pis_custom`).
Неуказанные поля остаются у пресета. Стили пишет конвертер в DOCX сам — вручную в шаблон добавлять не нужно.
## Как подключить
Позже побеждает (deep-merge только указанных ключей):
1. Встроенный пресет типа документа
2. `md2gost.styles.json` рядом с `.md` (если есть)
3. `--styles путь.json` или путь в GUI: **Настройки → Файлы → Стили JSON**
Файл рядом с exe при первом запуске **не создаётся**.
```bash
python -m md2gost report.md -o report.docx --type practice --styles examples/md2gost.styles.json
```
Пример: [`examples/md2gost.styles.json`](../examples/md2gost.styles.json).
## Схема
Два блока. Неизвестный ключ или имя стиля — ошибка.
```json
{
"page": {
"left_mm": 30,
"right_mm": 10,
"top_mm": 20,
"bottom_mm": 20
},
"styles": {
"Heading 1": {
"alignment": "center",
"size_pt": 14,
"all_caps": true
}
}
}
```
### `page`
| Ключ | Единица | Смысл |
|------|---------|--------|
| `left_mm` / `right_mm` / `top_mm` / `bottom_mm` | мм | Поля страницы |
### Имена стилей
`Normal`, `Heading 1`, `Heading 2`, `Heading 3`, `Caption Figure`, `Caption Table`, `Название таблицы`, `Caption Listing`, `Caption`, `Code`, `Table Text`, `Bibliography`, `Bibliography Heading`, `toc 1`, `toc 2`, `toc 3`, `Footer`, `Hyperlink`, `FollowedHyperlink`, `Space After Table`.
### Поля стиля
| Ключ | Тип / значения |
|------|----------------|
| `font_name` | строка |
| `size_pt` | число (pt) |
| `bold`, `italic`, `all_caps`, `underline` | bool |
| `alignment` | `left` \| `center` \| `justify` |
| `first_line_indent_cm`, `left_indent_cm`, `right_indent_cm` | см |
| `space_before_mm`, `space_after_mm` | мм |
| `line_spacing` | `1.0` \| `1.5` |
| `page_break_before`, `keep_with_next`, `widow_control` | bool |
Не в JSON: табы оглавления (считаются от ширины полосы), отступы списков, формулы из шаблона, цвет (всегда чёрный).
-187
View File
@@ -1,187 +0,0 @@
# Автотитульник
md2gost умеет **сам собрать титульный лист** из вшитого шаблона `TitleTemplate.docx`, подставив институт, кафедру, дисциплину, преподавателя, номер работы, ФИО и группу.
Готовый чужой DOCX титула (`--title` / «Настройки → Файлы → Титульный лист») по-прежнему работает и **полностью отключает** автогенерацию.
---
## Когда титул генерируется
Автотитул **по умолчанию выключен**. Включается явно:
- CLI: `--auto-title`
- GUI: галочка **«Автотитул»**
При включённом автотитуле он собирается, если одновременно:
1. **Не задан** явный путь к титульному DOCX (`--title` пуст, в GUI поле «Титульный лист» пустое).
2. Рядом с `.md` есть файл **`info_conv.yaml`** *или* в начале Markdown есть блок **\`\`\`title**.
Если автотитул выключен или нет ни yaml, ни блока `title` — титул не вставляется (готовый DOCX по `--title` по-прежнему можно передать отдельно).
ФИО и группа **обязательны** для генерации: из профиля GUI / `md2gost.user.json` или из `--student` / `--group`. Без них конвертация с `--auto-title` завершится ошибкой с подсказкой.
---
## Быстрый сценарий (GUI)
1. Первый запуск → окно **«Данные студента»**: введите **ФИО** и **группу**, сохраните.
Позже: **Настройки → Студент…**.
2. В папке с отчётом создайте `info_conv.yaml` (см. ниже).
3. В начале `.md` при необходимости добавьте блок \`\`\`title с номером работы и годом.
4. Включите галочку **«Автотитул»** на главном окне.
5. **Не** указывайте готовый титул в «Настройки → Файлы», если хотите автогенерацию.
6. Конвертируйте как обычно — перед телом отчёта появится титул.
Профиль студента хранится в `md2gost.user.json` рядом с приложением (рядом с exe или в текущей папке при `python -m md2gost`) — тот же каталог, что и `md2gost.schemes.json`. В том же файле блок `metadata` — свойства DOCX (автор/название/примечание); GUI: **Настройки → Метаданные…**, CLI: `--doc-*`. Это не поля титульного листа.
---
## `info_conv.yaml` (данные курса / кафедры)
Файл кладётся **в тот же каталог**, что и конвертируемый `.md`. Имя строго: `info_conv.yaml`.
Пример:
```yaml
Институт: Институт информационных технологий (ИИТ)
Кафедра: Кафедра цифровой трансформации (ЦТ)
Дисциплина: Проектирование архитектуры цифровой организации
Преподаватель: Иванов Иван Иванович
Должность: старший преподаватель, кафедра ЦТ
```
Формат — плоский список `ключ: значение` (UTF-8). Вложенный YAML и списки не нужны. Строки с `#` в начале — комментарии; хвост ` # …` в значении отрезается.
Один `info_conv.yaml` удобно держать на весь семестр/дисциплину и не копировать институт с кафедрой в каждый отчёт.
---
## Блок `title` в Markdown
Опциональный блок в **начале** файла (до `# *СОДЕРЖАНИЕ`), ограда языка `title`. Перед конвертацией он **вырезается** из тела отчёта и не попадает в DOCX как код.
Типичное использование — номер работы и год:
````markdown
```title
number: 1
year: 2026
```
# *СОДЕРЖАНИЕ
[TOC]
````
Можно переопределить любые академические поля прямо в блоке (они сильнее yaml):
````markdown
```title
number: 3
year: 2026
discipline: Другая формулировка дисциплины
teacher: Петров П. П.
```
````
Английские ключи тоже принимаются: `institute`, `department`, `discipline`, `teacher`, `teacher_position`, `number`, `year`.
---
## Поля: куда попадают и откуда берутся
| Поле на титуле | Ключи (любой из вариантов) | Источник |
|----------------|----------------------------|----------|
| Институт | `Институт`, `Institute`, `institute`; опечатка `Инститиут` | yaml / \`\`\`title |
| Кафедра | `Кафедра`, `Department`, `department` | yaml / \`\`\`title |
| Дисциплина (в «…») | `Дисциплина`, `Discipline`, `discipline` | yaml / \`\`\`title |
| № практической работы | `number`, `номер`, `№`, `n` | \`\`\`title (иначе `1`) |
| Группа («студент группы …») | — | профиль GUI / `--group` |
| ФИО студента | — | профиль GUI / `--student` |
| Должность преподавателя | `Должность`, `должность преподавателя`, `teacher_position` | yaml / \`\`\`title |
| ФИО преподавателя | `Преподаватель`, `Преподователь`, `Teacher`, `teacher` | yaml / \`\`\`title |
| Год («Москва … г.») | `year`, `год` | \`\`\`title (иначе текущий календарный год) |
Строка «ОТЧЁТ ПО ПРАКТИЧЕСКОЙ РАБОТЕ» и шапка МИРЭА в шаблоне **не** заполняются из переменных — это фиксированный текст шаблона.
ФИО/`группа` из yaml или \`\`\`title **игнорируются** (даже если написать `Студент:` / `Группа:`) — студент всегда из профиля или CLI.
---
## Приоритет слияния
```
Академические поля: info_conv.yaml < ```title (блок сильнее)
Студент / группа: md2gost.user.json < --student / --group
Явный титул DOCX: --title / путь в GUI → генератор не вызывается
```
`year` без значения → текущий год. `number` без значения → `1`.
---
## CLI
```bash
# автотитул выкл. по умолчанию — только тело отчёта
python -m md2gost report.md -o report.docx
# включить автотитул (yaml + профиль из md2gost.user.json)
python -m md2gost report.md -o report.docx --auto-title
# ФИО и группа на один прогон
python -m md2gost report.md --auto-title --student "Тарасов Игорь Алексеевич" --group ИНБО-31-23
# свой готовый титул — автогенерация не используется
python -m md2gost report.md --title title.docx
```
---
## Пример структуры папки
```
Отчет_практики/
info_conv.yaml ← институт, кафедра, дисциплина, препод
report_pr1.md ← в начале ```title с number/year
figures/
```
`report_pr1.md`:
````markdown
```title
number: 1
year: 2026
```
# *СОДЕРЖАНИЕ
[TOC]
# *ВВЕДЕНИЕ
````
---
## Частые вопросы
**Титул не появился.**
Проверьте: включён ли `--auto-title` / галочка «Автотитул»; нет ли пути в «Титульный лист» / `--title`; есть ли `info_conv.yaml` или \`\`\`title; заполнены ли ФИО и группа.
**Не тот номер работы.**
Задайте `number:` в \`\`\`title — из yaml номер не читается (только из блока или дефолт `1`).
**Нужен другой шаблон вёрстки.**
Сейчас слоты привязаны к bundled `TitleTemplate.docx`. Чужой макет — собирайте титул вручную и передавайте через `--title`.
**Задание (бланк).**
Автотитул не заменяет бланк задания: по-прежнему `--assignment` / «Бланк задания» в GUI.
**Где лежит профиль.**
`md2gost.user.json` рядом с приложением (см. каталог схем). Не коммитьте его с чужими ФИО в общие репозитории отчётов — это локальные данные студента.
-66
View File
@@ -1,66 +0,0 @@
# Типы документов
Задаётся флагом `--type` / выбором в GUI. Профили: [`md2gost/profiles.py`](../md2gost/profiles.py).
## Сводка
| Тип | Стили | Нумерация объектов | Источники | Структура |
|-----|--------|-------------------|-----------|-----------|
| `practice` | МИРЭА | по разделам (1.1, 2.1) | 5–7, ≤5 лет | Введение, разделы, заключение, список, приложения |
| `coursework` | МИРЭА | по разделам | 5–7, ≤5 лет | то же |
| `vkr` | МИРЭА | по разделам | ≥10 в **каждом** разделе списка, ≤5 лет | + приложение «Графический материал»; ссылки `[1.5]` |
| `PIS_custom` | ПИС | сквозная (1, 2, 3) | не требуются | H1 = практические работы; без введения/заключения по умолчанию |
| `APID_coursework` | МИРЭА | по разделам | 7–20, ≤5 лет | обязательные главы/пункты АПИД (см. ниже) |
## coursework / practice
Спецразделы с `*`, нумерованная основная часть. В DOCX: H1 слева с отступом (кроме СОДЕРЖАНИЕ / СПИСОК — по центру).
Проверка: `--check` / `--strict`.
## vkr
- Список источников **с разделами**; в каждом ≥10 записей.
- Ссылки вида `[1.5]`, при цитировании `[2.18, c. 21-25]`.
- Обязательное приложение с текстом «Графический материал» в названии.
## PIS_custom
Итоговый отчёт по практическим работам.
```markdown
# *СОДЕРЖАНИЕ
[TOC]
# Практическая работа №1. Название работы
## Цель работы
## Ход работы
## Выводы
# Практическая работа №2. …
```
- H1 **без** `*` (кроме СОДЕРЖАНИЕ): в DOCX — ПРОПИСНЫМИ по центру.
- H2 с абзацным отступом.
- Титул («Отчёт по практическим работам …») — отдельный DOCX: `--title title.docx`.
Пример: [`examples/pis_custom.md`](../examples/pis_custom.md).
Промпт: [`prompts/generate-pis-custom-report.md`](../prompts/generate-pis-custom-report.md).
## APID_coursework
Курсовая «Архитектура приложений и данных» (методичка Аншиной/Лагуновой). Оформление как у `coursework`, плюс проверка заголовков:
1. Теоретические аспекты …
2. Прикладные аспекты …
- 2.1 Описание проекта …
- 2.2 Описание роли …
- 2.3 Описание архитектуры …
- 2.4 Варианты развития архитектуры …
Источники: 720.
```bash
python -m md2gost report.md -o report.docx --type APID_coursework --check --title title.docx --assignment assignment.docx
```
-46
View File
@@ -1,46 +0,0 @@
# Импорт Word → Markdown (word2md)
Обратный пайплайн: **DOCX → Markdown** в диалекте md2gost. Удобно, если отчёт уже набран в Word (или собран md2gost раньше), а дальше править удобнее в `.md`.
Это **эвристический** импорт, не lossless round-trip: исходник UML/Mermaid, `%id` из исходного md и язык fence у листинга из DOCX не восстанавливаются.
## Запуск
```bash
python -m word2md report.docx -o report.md
word2md report.docx
python -m md2gost report.docx -o report.md # тот же импорт через md2gost
```
В GUI: перетащите `.docx` или кнопка **«Импорт DOCX→MD»**.
Картинки пишутся в каталог `<stem>_media/` рядом с `.md` (или `--media-dir`).
| Флаг | Смысл |
|------|--------|
| `-o` / `--output` | путь к `.md` |
| `--media-dir` | каталог картинок |
| `--keep-toc-pages` | не выкидывать строки содержания Word (по умолчанию только `[TOC]`) |
| `--pagebreaks` | писать `---` на разрывах страниц |
## Что распознаётся
- заголовки `Heading N` / спецразделы → `# *ВВЕДЕНИЕ`, `# 1 …`
- содержание → `# *СОДЕРЖАНИЕ` + `[TOC]` (поле TOC и строки `toc N` отбрасываются)
- подписи `Рисунок N — …`, `Таблица N`, `Листинг N` (+ «Продолжение…» склеивается)
- таблицы с merge → `^` / `>`
- листинги стиля `Code`
- формулы (таблица Formula / OMML) → `$$…$$`
- библиография `[1]: …`, ссылки `[1]` в тексте
- второй проход: `Рисунок 1.1``@Рисунок:fig1_1` (если номер известен по подписи)
Титул и бланк задания до первого H1/спецраздела пропускаются. Колонтитулы не импортируются.
## Ограничения
- Нет восстановления PlantUML / Mermaid (только PNG/JPEG из файла)
- OMML → формула — best-effort, не идеальный LaTeX
- Надписи, SmartArt, сноски, плавающие рисунки — пропуск с записью в лог
- Титул, свёрстанный большой таблицей, может попасть в поток, если walker уже «стартовал» — обычно титул до первого Heading пропускается
После импорта имеет смысл прогнать `python -m md2gost report.md --check`.
-207
View File
@@ -1,207 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
xmlns:math="http://www.w3.org/1998/Math/MathML"
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
xmlns:dom="http://www.w3.org/2001/xml-events"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
office:version="1.3"
office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta>
<dc:title>md2fodt</dc:title>
<meta:generator>md2fodt</meta:generator>
</office:meta>
<office:styles>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:text-align="justify" style:justify-single-word="false"
fo:orphans="2" fo:widows="2"/>
<style:text-properties style:font-name="Times New Roman" fo:font-size="14pt"
style:font-name-asian="Times New Roman" style:font-size-asian="14pt"
style:font-name-complex="Times New Roman" style:font-size-complex="14pt"/>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text">
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm"
fo:line-height="150%" fo:text-align="justify"
fo:text-indent="1.25cm"/>
<style:text-properties style:font-name="Times New Roman" fo:font-size="14pt"/>
</style:style>
<style:style style:name="Heading" style:family="paragraph" style:class="text"/>
<style:style style:name="Heading_20_1" style:display-name="Heading 1"
style:family="paragraph" style:parent-style-name="Heading" style:default-outline-level="1"
style:class="text">
<style:paragraph-properties fo:margin-top="0.4cm" fo:margin-bottom="0.3cm"
fo:text-align="left" fo:text-indent="1.25cm" fo:line-height="150%"
fo:keep-with-next="always"/>
<style:text-properties fo:font-weight="bold" style:font-name="Times New Roman"
fo:font-size="14pt"/>
</style:style>
<style:style style:name="Heading_20_2" style:display-name="Heading 2"
style:family="paragraph" style:parent-style-name="Heading" style:default-outline-level="2"
style:class="text">
<style:paragraph-properties fo:margin-top="0.3cm" fo:margin-bottom="0.2cm"
fo:text-align="left" fo:text-indent="1.25cm" fo:line-height="150%"
fo:keep-with-next="always"/>
<style:text-properties fo:font-weight="bold" style:font-name="Times New Roman"
fo:font-size="14pt"/>
</style:style>
<style:style style:name="Heading_20_3" style:display-name="Heading 3"
style:family="paragraph" style:parent-style-name="Heading" style:default-outline-level="3"
style:class="text">
<style:paragraph-properties fo:margin-top="0.2cm" fo:margin-bottom="0.2cm"
fo:text-align="left" fo:text-indent="1.25cm" fo:line-height="150%"
fo:keep-with-next="always"/>
<style:text-properties fo:font-weight="bold" style:font-name="Times New Roman"
fo:font-size="14pt"/>
</style:style>
<style:style style:name="Caption" style:family="paragraph" style:class="extra">
<style:paragraph-properties fo:text-align="center" fo:text-indent="0cm"
fo:margin-top="0.2cm" fo:margin-bottom="0.2cm" fo:line-height="150%"/>
<style:text-properties style:font-name="Times New Roman" fo:font-size="14pt"/>
</style:style>
<style:style style:name="Preformatted_20_Text" style:display-name="Preformatted Text"
style:family="paragraph" style:class="html">
<style:paragraph-properties fo:text-align="left" fo:text-indent="0cm"
fo:margin-left="0cm" fo:line-height="100%"/>
<style:text-properties style:font-name="Courier New" fo:font-size="12pt"/>
</style:style>
<style:style style:name="Centered" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties fo:text-align="center" fo:text-indent="0cm"/>
</style:style>
<text:outline-style>
<text:outline-level-style text:level="1" style:num-format="">
<style:list-level-properties text:min-label-distance="0.4cm"/>
</text:outline-level-style>
<text:outline-level-style text:level="2" style:num-format="">
<style:list-level-properties text:min-label-distance="0.4cm"/>
</text:outline-level-style>
<text:outline-level-style text:level="3" style:num-format="">
<style:list-level-properties text:min-label-distance="0.4cm"/>
</text:outline-level-style>
</text:outline-style>
</office:styles>
<office:automatic-styles>
<style:page-layout style:name="pm1">
<style:page-layout-properties fo:page-width="21.0cm" fo:page-height="29.7cm"
style:num-format="1" style:print-orientation="portrait"
fo:margin-top="2.0cm" fo:margin-bottom="2.0cm"
fo:margin-left="3.0cm" fo:margin-right="1.0cm"
style:writing-mode="lr-tb"/>
</style:page-layout>
<style:style style:name="Tbold" style:family="text">
<style:text-properties fo:font-weight="bold"/>
</style:style>
<style:style style:name="Titalic" style:family="text">
<style:text-properties fo:font-style="italic"/>
</style:style>
<style:style style:name="Tcode" style:family="text">
<style:text-properties style:font-name="Courier New" fo:font-size="12pt"/>
</style:style>
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
<style:graphic-properties style:horizontal-pos="center" style:horizontal-rel="paragraph"
style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%"
draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%"
draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/>
</style:style>
<style:style style:name="Table1" style:family="table">
<style:table-properties table:border-model="collapsing" style:rel-width="100%"
table:align="margins"/>
</style:style>
<style:style style:name="Table1.A" style:family="table-column">
<style:table-column-properties style:rel-column-width="1000*"/>
</style:style>
<style:style style:name="Table1.1" style:family="table-cell">
<style:table-cell-properties fo:padding="0.1cm" fo:border="0.5pt solid #000000"/>
</style:style>
<style:style style:name="Pcell" style:family="paragraph" style:parent-style-name="Standard">
<style:paragraph-properties fo:text-indent="0cm" fo:text-align="left" fo:line-height="100%"/>
</style:style>
<style:style style:name="L1" style:family="list">
<text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols"
text:bullet-char="">
<style:list-level-properties text:space-before="0cm" text:min-label-width="0.75cm"/>
</text:list-level-style-bullet>
<text:list-level-style-number text:level="1" text:style-name="Numbering_20_Symbols"
style:num-suffix="." style:num-format="1">
<style:list-level-properties text:space-before="0cm" text:min-label-width="0.75cm"/>
</text:list-level-style-number>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="pm1"/>
</office:master-styles>
<office:body>
<office:text>
<text:p text:style-name="Centered">СОДЕРЖАНИЕ</text:p>
<text:table-of-content text:style-name="Standard" text:protected="false" text:name="TOC"><text:table-of-content-source text:outline-level="3"><text:index-title-template text:style-name="Centered">Содержание</text:index-title-template></text:table-of-content-source><text:index-body><text:p text:style-name="Standard">(Обновите содержание в LibreOffice Writer: ПКМ → Обновить индекс)</text:p></text:index-body></text:table-of-content>
<text:h text:style-name="Heading_20_1" text:outline-level="1">ВВЕДЕНИЕ</text:h>
<text:p text:style-name="Standard">В настоящей работе рассматривается задача построения информационной системы учёта. Цель работы — спроектировать архитектуру и реализовать прототип модуля обработки данных.</text:p>
<text:h text:style-name="Heading_20_1" text:outline-level="1">Анализ предметной области</text:h>
<text:p text:style-name="Standard">Предметная область связана с обработкой структурированных данных. Обзор подходов приведён в работах [1], [2].</text:p>
<text:p text:style-name="Standard">Структура системы показана на Рисунок ?.</text:p>
<text:p text:style-name="Centered"><draw:frame draw:style-name="fr1" draw:name="img1" text:anchor-type="as-char" svg:width="16cm" svg:height="9cm" draw:z-index="0"><draw:image xlink:href="Pictures/img.png" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" draw:mime-type="image/png"><office:binary-data>iVBORw0KGgoAAAANSUhEUgAAATYAAADwCAQAAAAgc4A/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfmBRgCOC6ZScdlAAAF+ElEQVR42u3d2XITRxiA0V8ty8I2LkKBl0re/33yFKQIEFZHNhg7F0ACxIuWUU8v57t0wUhMH3oWSz2T369DytGzZB8oV7AJNsEmwSbYJNgEm2CTYBNsEmyCTbBJsAk2CTbBJtgk2ASbBJtgE2wSbIJNgk2wCTYJNsEmwSbYJNgEm2CTYBNsEmyCTbBJsAk2CTbBJtgk2ASbBJtgU4ftlPk/YBqTiLiKz+Gp4rBtpXnsxYOYxfTfn1zHZVzEefwdV8YKtmGaxGEcxuyGn89iFg/jOhbxNi6MF2ybdhi/fDeb3YxxP/ZjEX/FJ2MG2/pv4CjmS/7Zvfg13sRbowbbOu3F0UoXxJN4HPN44bKhyka99XEQx2u8gf04dccGtlVntacxWfOq9WTNv6kusc3iaAMw83hq7GBb9tzreMOXPohDowfbMj264Z7aqj2+53aJYIuInXg0yFt/bPxgu39eG+b0/mCA+VFNY0vxcLAzP+dtsN3Z/oC3LQ7cAoHtbmzDNV36V13qEtuDgremprDNBn7JXWMI2+3Yyt6eGsI2LXx7agjbpPZ/gIyVYPtfQ3/s0RdhYLu1z4VvTw1h+1T49tQQtsuBD3wfjSFst5+znQ+6vXNjCNvtLQY9Y/PFZdju6GzAK9IzX+qD7a6u4sNgh+T3RhC2u3s70Hx05loUtvuvSIdYQuEq3hg/2JaZ2zafk17HpfGDbZmzrRcb3m87c74G27J93Gh5mIt4aexgW75FvFyT20U8d8ujwkZdMussrlZcMusL0hc+62FmW2d2e7bS7wCu43U8R83Mtl6X8ccSy5x+o2mZU9g27H18uGUB5/9mNAs4wzZQ1/Eu3n1dmn73h2P7ZVzEIhY+JAnbsF18nbumkTx0A7Y8fTaPuRqVYBNsEmyCTbBJsAk2CTbBJtgk2ASbBJtgE2wSbIJNgk2wCTYJtibajd88rBK2PNROYhan3T/1GbYs1KYRkeKkc26wZaIWuMGWjxpusGWk1js32LJS65sbbJmp9cwNtuzU+uUG2wjUeuUG2yjU+uQG20jUeuQG22jU+uMG24jUeuMG26jU+uIG28jUeuIG2+jU+uEGWwHUeuEGWxHU+uAGWyHUeuAGWzHU2ucGW0HUWucGW1HU2uYGW2HUWuYGW3HU2uUGW4HUWuUGW5HU2uQGW6HUWuQGW7HU2uMGW8HUWuMGW9HU2uKWah78/YyvNo/TUai1xC3VS+0kjuIg26sdj7qrUpzEA9jGPKRN4mkWbmMdQH8cqOPquaV6qUVEFm4lUGuDW6qZWg5uuyOeq7XGLdVNbdvcduO0qF1UN7dUO7VtciuNWu3cUv3UtsWtRGp1c0stUNsGt1Kp1cwttUFtaG4lU6uXW2qF2pDc5oVTq5VbaofaUNzmcVLFbqmPW2qJ2hDcaqFWI7fUFrVNudVErT5uqTVqm3CrjVpt3FJ71L5xe9gBtbq4pRapfeH2ZCVutVKriVtqk9qq3GqmVg+31Cq1VbjVTq0Wbqldastya4FaHdxSy9SW4dYKtRq4pbap3cetJWrlc0utU7uLW2vUSueW2qd2G7cWqZXNLfVA7SZurVIrmVvqg9rP3FqmVi631Au177m1Tq1UbjtlUMv1YcVJPIlZHHaxxEmK4/gzzs1sP89q+d7GJB51s5pOabNbKoHaNNQDt4Qabl1gQ60vbgk13JrHhlp/3BJquDWNDbU+uSXUcGsWG2r9ckuo9cZtvKWgU15qp6iN3mQ0bikvNc/46JlbQg23xrChhlsmbKjhlgkbarhlwoZa6dz2WsE2R614bsfZuKXtUjtBDbcc2FDDLRM21HDLhA013DJhQw23TNhQwy0TNtRwy4QNNdwyYUOtFW77pWNDrR1uR1vhllBTLm4JNeXillBTLm4JNeXillBTLm4JNeXillBTLm4JNeXillBTLm4JNeXillBTLm4JNeXillBTLm4JNeXillBTLm47q8l8ZV9r7VbCtrC/lPdqVIJNsEmwCTbBJsEm2CTYBJtgk2ATbBJsgk2wSbAJNgk2waYO+weAKJXRNONZaQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wNS0yNFQwMjo1Njo0NiswMDowMOfErAYAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDUtMjRUMDI6NTY6NDYrMDA6MDCWmRS6AAAAAElFTkSuQmCC</office:binary-data></draw:image></draw:frame></text:p>
<text:p text:style-name="Caption"><text:bookmark text:name="fig-arch"/>Рисунок 1 — Архитектура информационной системы</text:p>
<text:p text:style-name="Standard">Сравнение вариантов реализации представлено в Таблица 1.</text:p>
<text:p text:style-name="Caption"><text:bookmark text:name="tab-cmp"/>Таблица 1 — Сравнение подходов</text:p>
<table:table table:name="Table1" table:style-name="Table1"><table:table-column table:style-name="Table1.A" style:rel-column-width="333*"/><table:table-column table:style-name="Table1.A" style:rel-column-width="333*"/><table:table-column table:style-name="Table1.A" style:rel-column-width="333*"/><table:table-header-rows><table:table-row><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Подход</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Сложность</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Гибкость</text:p></table:table-cell></table:table-row></table:table-header-rows><table:table-row><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Монолит</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">низкая</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">низкая</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Модульный</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">средняя</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">высокая</text:p></table:table-cell></table:table-row><table:table-row><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">Микросервисы</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">высокая</text:p></table:table-cell><table:table-cell table:style-name="Table1.1" office:value-type="string"><text:p text:style-name="Pcell">высокая</text:p></table:table-cell></table:table-row></table:table>
<text:p text:style-name="Standard">Основные требования к системе:</text:p>
<text:list text:style-name="L1">
<text:list-item>
<text:p text:style-name="Standard">поддержка импорта данных;</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="Standard">формирование отчётности;</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="Standard">разграничение прав доступа.</text:p>
</text:list-item>
</text:list>
<text:p text:style-name="Standard">Порядок разработки включает следующие этапы:</text:p>
<text:list text:style-name="L1">
<text:list-item>
<text:p text:style-name="Standard">анализ требований;</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="Standard">проектирование архитектуры;</text:p>
</text:list-item>
<text:list-item>
<text:p text:style-name="Standard">реализация прототипа.</text:p>
</text:list-item>
</text:list>
<text:h text:style-name="Heading_20_1" text:outline-level="1">Проектирование</text:h>
<text:p text:style-name="Standard">Ключевое соотношение для оценки объёма данных задаётся формулой:</text:p>
<text:p text:style-name="Centered"><text:bookmark text:name="eq-eq1"/><text:span text:style-name="Tcode">V = N \times S</text:span></text:p>
<text:p text:style-name="Standard">где <text:span text:style-name="Tcode">N</text:span> — число записей, <text:span text:style-name="Tcode">S</text:span> — средний размер записи. Использование зависимости приведено в (формула ?).</text:p>
<text:p text:style-name="Standard">Фрагмент реализации:</text:p>
<text:p text:style-name="Caption"><text:bookmark text:name="lst-code1"/>Листинг 1 — Процедура расчёта объёма</text:p>
<text:p text:style-name="Preformatted_20_Text">def<text:s/>volume(n:<text:s/>int,<text:s/>s:<text:s/>float)<text:s/>-&gt;<text:s/>float:</text:p>
<text:p text:style-name="Preformatted_20_Text"><text:s text:c="4"/>return<text:s/>n<text:s/>*<text:s/>s</text:p>
<text:p text:style-name="Standard">Пример вызова приведён в Листинг 1.</text:p>
<text:h text:style-name="Heading_20_1" text:outline-level="1">ЗАКЛЮЧЕНИЕ</text:h>
<text:p text:style-name="Standard">В работе выполнен анализ предметной области, спроектирована архитектура и реализован прототип модуля расчёта.</text:p>
<text:h text:style-name="Heading_20_1" text:outline-level="1">СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ</text:h>
<text:h text:style-name="Heading_20_1" text:outline-level="1">ПРИЛОЖЕНИЯ</text:h>
<text:h text:style-name="Heading_20_2" text:outline-level="2">Приложение А Исходный код модуля</text:h>
<text:p text:style-name="Standard">Дополнительный код модуля вынесен в приложение.</text:p>
<text:h text:style-name="Heading_20_1" text:outline-level="1">СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ</text:h>
<text:p text:style-name="Standard">[1] Иванов И. И. Информационные системы. — М.: Наука, 2023. — 120 с.</text:p>
<text:p text:style-name="Standard">[2] Петров П. П. Базы данных: учебник. — СПб.: Питер, 2022. — 200 с.</text:p>
<text:p text:style-name="Standard">[3] ГОСТ 7.32-2017. Отчет о научно-исследовательской работе. — М., 2022.</text:p>
<text:p text:style-name="Standard">[4] Сидоров С. С. Разработка на Python. — М.: ДМК Пресс, 2024. — 300 с.</text:p>
<text:p text:style-name="Standard">[5] Козлов К. К. Анализ данных. — М.: Бином, 2022. — 150 с.</text:p>
<text:p text:style-name="Standard">[6] Смирнова А. А. Проектирование ПО. — М.: Инфра-М, 2023. — 180 с.</text:p>
</office:text>
</office:body>
</office:document>
-77
View File
@@ -1,77 +0,0 @@
# *СОДЕРЖАНИЕ
[TOC]
# *ВВЕДЕНИЕ
В настоящей работе рассматривается задача построения информационной системы учёта. Цель работы — спроектировать архитектуру и реализовать прототип модуля обработки данных.
# Анализ предметной области
Предметная область связана с обработкой структурированных данных. Обзор подходов приведён в работах [1], [2].
Структура системы показана на @Рисунок:arch.
![Архитектура](img.png "%arch Архитектура информационной системы")
Сравнение вариантов реализации представлено в @Таблица:cmp.
%cmp Сравнение подходов
| Подход | Сложность | Гибкость |
|--------|-----------|----------|
| Монолит | низкая | низкая |
| Модульный | средняя | высокая |
| Микросервисы | высокая | высокая |
Основные требования к системе:
- поддержка импорта данных;
- формирование отчётности;
- разграничение прав доступа.
Порядок разработки включает следующие этапы:
1. анализ требований;
2. проектирование архитектуры;
3. реализация прототипа.
# Проектирование
Ключевое соотношение для оценки объёма данных задаётся формулой:
%eq1
$$
V = N \times S
$$
где $N$ — число записей, $S$ — средний размер записи. Использование зависимости приведено в (@Формула:eq1).
Фрагмент реализации:
%code1 Процедура расчёта объёма
```python
def volume(n: int, s: float) -> float:
return n * s
```
Пример вызова приведён в @Листинг:code1.
# *ЗАКЛЮЧЕНИЕ
В работе выполнен анализ предметной области, спроектирована архитектура и реализован прототип модуля расчёта.
# *СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
[1]: Иванов И. И. Информационные системы. — М.: Наука, 2023. — 120 с.
[2]: Петров П. П. Базы данных: учебник. — СПб.: Питер, 2022. — 200 с.
[3]: ГОСТ 7.32-2017. Отчет о научно-исследовательской работе. — М., 2022.
[4]: Сидоров С. С. Разработка на Python. — М.: ДМК Пресс, 2024. — 300 с.
[5]: Козлов К. К. Анализ данных. — М.: Бином, 2022. — 150 с.
[6]: Смирнова А. А. Проектирование ПО. — М.: Инфра-М, 2023. — 180 с.
# *ПРИЛОЖЕНИЯ
## Приложение А Исходный код модуля
Дополнительный код модуля вынесен в приложение.
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

-21
View File
@@ -1,21 +0,0 @@
{
"page": {
"left_mm": 20,
"right_mm": 20,
"top_mm": 20,
"bottom_mm": 20
},
"styles": {
"Heading 1": {
"alignment": "center",
"size_pt": 14,
"all_caps": true,
"left_indent_cm": 0,
"first_line_indent_cm": 0
},
"Normal": {
"first_line_indent_cm": 1.25,
"line_spacing": 1.5
}
}
}
-50
View File
@@ -1,50 +0,0 @@
# *СОДЕРЖАНИЕ
[TOC]
# Практическая работа №1. Формирование требований к системе
## Цель работы
Сформировать требования к информационной системе на основе анализа предметной области.
## Ход работы
В ходе работы выполнен анализ предметной области. Структура системы показана на @Рисунок:arch.
![Архитектура](img.png "%arch Архитектура информационной системы")
Сравнение подходов приведено в @Таблица:cmp.
%cmp Сравнение подходов
| Подход | Сложность | Гибкость |
|--------|-----------|----------|
| Монолит | низкая | низкая |
| Модульный | средняя | высокая |
## Выводы
Сформулированы функциональные и нефункциональные требования к системе.
# Практическая работа №2. Моделирование процессов
## Цель работы
Построить модель бизнес-процессов.
## Ход работы
Построена модель as-is и to-be. Фрагмент спецификации:
%spec Фрагмент спецификации требований
```text
REQ-1: Система должна поддерживать импорт данных.
REQ-2: Система должна формировать отчёты.
```
См. @Листинг:spec.
## Выводы
Модель процессов согласована с требованиями из практической работы №1.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More