1 parent
16d8426119
commit
66158e222e
398 files changed
+85259
-270637
No files matched your search
@@ -1,9 +1,15 @@
|
||||
{
|
||||
"extends": "C:\\Users\\zhang\\Documents\\GitHub\\AgentCompany\\electron-builder.yml",
|
||||
"extends": "/Users/zacharyzhang/Documents/Github/AgentCompany/electron-builder.yml",
|
||||
"directories": {
|
||||
"output": "C:\\Users\\zhang\\Documents\\GitHub\\AgentCompany\\build\\release"
|
||||
"output": "/Users/zacharyzhang/Documents/Github/AgentCompany/build/release"
|
||||
},
|
||||
"extraMetadata": {
|
||||
"version": "0.4.148"
|
||||
"version": "0.4.136"
|
||||
},
|
||||
"mac": {
|
||||
"hardenedRuntime": false,
|
||||
"target": [
|
||||
"zip"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,3 @@
|
||||
x64:
|
||||
firstOrDefaultFilePatterns:
|
||||
- '!**/node_modules/**'
|
||||
- '!assets{,/**/*}'
|
||||
- '!build/release{,/**/*}'
|
||||
- out/**
|
||||
- package.json
|
||||
- assets/icon.png
|
||||
- assets/tray-icon*.png
|
||||
- '!**/*.{iml,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,suo,xproj,cc,d.ts,mk,a,o,obj,forge-meta,pdb}'
|
||||
- '!**/._*'
|
||||
- '!**/electron-builder.{yaml,yml,json,json5,toml,ts}'
|
||||
- '!**/{.git,.hg,.svn,CVS,RCS,SCCS,__pycache__,.DS_Store,thumbs.db,.gitignore,.gitkeep,.gitattributes,.npmignore,.idea,.vs,.flowconfig,.jshintrc,.eslintrc,.circleci,.yarn-integrity,.yarn-metadata.json,yarn-error.log,yarn.lock,package-lock.json,npm-debug.log,pnpm-lock.yaml,bun.lock,bun.lockb,appveyor.yml,.travis.yml,circle.yml,.nyc_output,.husky,.github,electron-builder.env}'
|
||||
- '!.yarn{,/**/*}'
|
||||
- '!.editorconfig'
|
||||
- '!.yarnrc.yml'
|
||||
nodeModuleFilePatterns:
|
||||
- '**/*'
|
||||
- out/**
|
||||
- package.json
|
||||
- assets/icon.png
|
||||
- assets/tray-icon*.png
|
||||
arm64:
|
||||
firstOrDefaultFilePatterns:
|
||||
- '!**/node_modules/**'
|
||||
@@ -42,5 +20,3 @@ arm64:
|
||||
- package.json
|
||||
- assets/icon.png
|
||||
- assets/tray-icon*.png
|
||||
nsis:
|
||||
script: "!include \"C:\\Users\\zhang\\Documents\\GitHub\\AgentCompany\\node_modules\\.pnpm\\app-builder-lib@26.8.1_dmg-_62d31da0b96a3ea7b7d51a6bbe3b3b6e\\node_modules\\app-builder-lib\\templates\\nsis\\include\\StdUtils.nsh\"\n!addincludedir \"C:\\Users\\zhang\\Documents\\GitHub\\AgentCompany\\node_modules\\.pnpm\\app-builder-lib@26.8.1_dmg-_62d31da0b96a3ea7b7d51a6bbe3b3b6e\\node_modules\\app-builder-lib\\templates\\nsis\\include\"\n!macro _isUpdated _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"updated\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isUpdated `\"\" isUpdated \"\"`\n\n!macro _isForceRun _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"force-run\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isForceRun `\"\" isForceRun \"\"`\n\n!macro _isKeepShortcuts _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"keep-shortcuts\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isKeepShortcuts `\"\" isKeepShortcuts \"\"`\n\n!macro _isNoDesktopShortcut _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"no-desktop-shortcut\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isNoDesktopShortcut `\"\" isNoDesktopShortcut \"\"`\n\n!macro _isDeleteAppData _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"delete-app-data\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isDeleteAppData `\"\" isDeleteAppData \"\"`\n\n!macro _isForAllUsers _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"allusers\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isForAllUsers `\"\" isForAllUsers \"\"`\n\n!macro _isForCurrentUser _a _b _t _f\n ${StdUtils.TestParameter} $R9 \"currentuser\"\n StrCmp \"$R9\" \"true\" `${_t}` `${_f}`\n!macroend\n!define isForCurrentUser `\"\" isForCurrentUser \"\"`\n\n!macro addLangs\n !insertmacro MUI_LANGUAGE \"English\"\n !insertmacro MUI_LANGUAGE \"German\"\n !insertmacro MUI_LANGUAGE \"French\"\n !insertmacro MUI_LANGUAGE \"SpanishInternational\"\n !insertmacro MUI_LANGUAGE \"SimpChinese\"\n !insertmacro MUI_LANGUAGE \"TradChinese\"\n !insertmacro MUI_LANGUAGE \"Japanese\"\n !insertmacro MUI_LANGUAGE \"Korean\"\n !insertmacro MUI_LANGUAGE \"Italian\"\n !insertmacro MUI_LANGUAGE \"Dutch\"\n !insertmacro MUI_LANGUAGE \"Danish\"\n !insertmacro MUI_LANGUAGE \"Swedish\"\n !insertmacro MUI_LANGUAGE \"Norwegian\"\n !insertmacro MUI_LANGUAGE \"Finnish\"\n !insertmacro MUI_LANGUAGE \"Russian\"\n !insertmacro MUI_LANGUAGE \"Portuguese\"\n !insertmacro MUI_LANGUAGE \"PortugueseBR\"\n !insertmacro MUI_LANGUAGE \"Polish\"\n !insertmacro MUI_LANGUAGE \"Ukrainian\"\n !insertmacro MUI_LANGUAGE \"Czech\"\n !insertmacro MUI_LANGUAGE \"Slovak\"\n !insertmacro MUI_LANGUAGE \"Hungarian\"\n !insertmacro MUI_LANGUAGE \"Arabic\"\n !insertmacro MUI_LANGUAGE \"Turkish\"\n !insertmacro MUI_LANGUAGE \"Thai\"\n !insertmacro MUI_LANGUAGE \"Vietnamese\"\n!macroend\n\n!addplugindir /x86-unicode \"C:\\Users\\zhang\\AppData\\Local\\electron-builder\\Cache\\nsis\\nsis-resources-3.4.1-nsis-resources-3.4.1\\plugins\\x86-unicode\"\n!include \"C:\\Users\\zhang\\AppData\\Local\\Temp\\t-ZPKi2B\\6-messages.nsh\"\n\n!include \"common.nsh\"\n!include \"extractAppPackage.nsh\"\n\n# https://github.com/electron-userland/electron-builder/issues/3972#issuecomment-505171582\nCRCCheck off\nWindowIcon Off\nAutoCloseWindow True\nRequestExecutionLevel ${REQUEST_EXECUTION_LEVEL}\n\nFunction .onInit\n !ifndef SPLASH_IMAGE\n SetSilent silent\n !endif\n\n !insertmacro check64BitAndSetRegView\nFunctionEnd\n\nFunction .onGUIInit\n InitPluginsDir\n\n !ifdef SPLASH_IMAGE\n File /oname=$PLUGINSDIR\\splash.bmp \"${SPLASH_IMAGE}\"\n BgImage::SetBg $PLUGINSDIR\\splash.bmp\n BgImage::Redraw\n !endif\nFunctionEnd\n\nSection\n !ifdef SPLASH_IMAGE\n HideWindow\n !endif\n\n StrCpy $INSTDIR \"$PLUGINSDIR\\app\"\n !ifdef UNPACK_DIR_NAME\n StrCpy $INSTDIR \"$TEMP\\${UNPACK_DIR_NAME}\"\n !endif\n\n RMDir /r $INSTDIR\n SetOutPath $INSTDIR\n\n !ifdef APP_DIR_64\n !ifdef APP_DIR_ARM64\n !ifdef APP_DIR_32\n ${if} ${IsNativeARM64}\n File /r \"${APP_DIR_ARM64}\\*.*\"\n ${elseif} ${RunningX64}\n File /r \"${APP_DIR_64}\\*.*\"\n ${else}\n File /r \"${APP_DIR_32}\\*.*\"\n ${endIf}\n !else\n ${if} ${IsNativeARM64}\n File /r \"${APP_DIR_ARM64}\\*.*\"\n ${else}\n File /r \"${APP_DIR_64}\\*.*\"\n {endIf}\n !endif\n !else\n !ifdef APP_DIR_32\n ${if} ${RunningX64}\n File /r \"${APP_DIR_64}\\*.*\"\n ${else}\n File /r \"${APP_DIR_32}\\*.*\"\n ${endIf}\n !else\n File /r \"${APP_DIR_64}\\*.*\"\n !endif\n !endif\n !else\n !ifdef APP_DIR_32\n File /r \"${APP_DIR_32}\\*.*\"\n !else\n !insertmacro extractEmbeddedAppPackage\n !endif\n !endif\n\n System::Call 'Kernel32::SetEnvironmentVariable(t, t)i (\"PORTABLE_EXECUTABLE_DIR\", \"$EXEDIR\").r0'\n System::CLine truncated
|
||||
@@ -1,21 +0,0 @@
|
||||
Copyright (c) Electron contributors
|
||||
Copyright (c) 2013-2020 GitHub Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"file_format_version": "1.0.0", "ICD": {"library_path": ".\\vk_swiftshader.dll", "api_version": "1.0.5"}}
|
||||
Binary file not shown.
@@ -0,0 +1,173 @@
|
||||
import {loadFont} from '@remotion/google-fonts/Inter';
|
||||
import {AbsoluteFill, spring, useCurrentFrame, useVideoConfig} from 'remotion';
|
||||
|
||||
const {fontFamily} = loadFont();
|
||||
|
||||
const COLOR_BAR = '#D4AF37';
|
||||
const COLOR_TEXT = '#ffffff';
|
||||
const COLOR_MUTED = '#888888';
|
||||
const COLOR_BG = '#0a0a0a';
|
||||
const COLOR_AXIS = '#333333';
|
||||
|
||||
// Ideal composition size: 1280x720
|
||||
|
||||
const Title: React.FC<{children: React.ReactNode}> = ({children}) => (
|
||||
<div style={{textAlign: 'center', marginBottom: 40}}>
|
||||
<div style={{color: COLOR_TEXT, fontSize: 48, fontWeight: 600}}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const YAxis: React.FC<{steps: number[]; height: number}> = ({
|
||||
steps,
|
||||
height,
|
||||
}) => (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
height,
|
||||
paddingRight: 16,
|
||||
}}
|
||||
>
|
||||
{steps
|
||||
.slice()
|
||||
.reverse()
|
||||
.map((step) => (
|
||||
<div
|
||||
key={step}
|
||||
style={{
|
||||
color: COLOR_MUTED,
|
||||
fontSize: 20,
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
{step.toLocaleString()}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Bar: React.FC<{
|
||||
height: number;
|
||||
progress: number;
|
||||
}> = ({height, progress}) => (
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height,
|
||||
backgroundColor: COLOR_BAR,
|
||||
borderRadius: '8px 8px 0 0',
|
||||
opacity: progress,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const XAxis: React.FC<{
|
||||
children: React.ReactNode;
|
||||
labels: string[];
|
||||
height: number;
|
||||
}> = ({children, labels, height}) => (
|
||||
<div style={{flex: 1, display: 'flex', flexDirection: 'column'}}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'flex-end',
|
||||
gap: 16,
|
||||
height,
|
||||
borderLeft: `2px solid ${COLOR_AXIS}`,
|
||||
borderBottom: `2px solid ${COLOR_AXIS}`,
|
||||
paddingLeft: 16,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: 16,
|
||||
paddingLeft: 16,
|
||||
marginTop: 12,
|
||||
}}
|
||||
>
|
||||
{labels.map((label) => (
|
||||
<div
|
||||
key={label}
|
||||
style={{
|
||||
flex: 1,
|
||||
textAlign: 'center',
|
||||
color: COLOR_MUTED,
|
||||
fontSize: 20,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MyAnimation = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const {fps, height} = useVideoConfig();
|
||||
|
||||
const data = [
|
||||
{month: 'Jan', price: 2039},
|
||||
{month: 'Mar', price: 2160},
|
||||
{month: 'May', price: 2327},
|
||||
{month: 'Jul', price: 2426},
|
||||
{month: 'Sep', price: 2634},
|
||||
{month: 'Nov', price: 2672},
|
||||
];
|
||||
|
||||
const minPrice = 2000;
|
||||
const maxPrice = 2800;
|
||||
const priceRange = maxPrice - minPrice;
|
||||
const chartHeight = height - 280;
|
||||
const yAxisSteps = [2000, 2400, 2800];
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
backgroundColor: COLOR_BG,
|
||||
padding: 60,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
fontFamily,
|
||||
}}
|
||||
>
|
||||
<Title>Gold Price 2024</Title>
|
||||
|
||||
<div style={{display: 'flex', flex: 1}}>
|
||||
<YAxis steps={yAxisSteps} height={chartHeight} />
|
||||
<XAxis height={chartHeight} labels={data.map((d) => d.month)}>
|
||||
{data.map((item, i) => {
|
||||
const progress = spring({
|
||||
frame: frame - i * 5 - 10,
|
||||
fps,
|
||||
config: {damping: 18, stiffness: 80},
|
||||
});
|
||||
|
||||
const barHeight =
|
||||
((item.price - minPrice) / priceRange) * chartHeight * progress;
|
||||
|
||||
return (
|
||||
<Bar key={item.month} height={barHeight} progress={progress} />
|
||||
);
|
||||
})}
|
||||
</XAxis>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
AbsoluteFill,
|
||||
interpolate,
|
||||
useCurrentFrame,
|
||||
useVideoConfig,
|
||||
} from 'remotion';
|
||||
|
||||
const COLOR_BG = '#ffffff';
|
||||
const COLOR_TEXT = '#000000';
|
||||
const FULL_TEXT = 'From prompt to motion graphics. This is Remotion.';
|
||||
const PAUSE_AFTER = 'From prompt to motion graphics.';
|
||||
const FONT_SIZE = 72;
|
||||
const FONT_WEIGHT = 700;
|
||||
const CHAR_FRAMES = 2;
|
||||
const CURSOR_BLINK_FRAMES = 16;
|
||||
const PAUSE_SECONDS = 1;
|
||||
|
||||
// Ideal composition size: 1280x720
|
||||
|
||||
const getTypedText = ({
|
||||
frame,
|
||||
fullText,
|
||||
pauseAfter,
|
||||
charFrames,
|
||||
pauseFrames,
|
||||
}: {
|
||||
frame: number;
|
||||
fullText: string;
|
||||
pauseAfter: string;
|
||||
charFrames: number;
|
||||
pauseFrames: number;
|
||||
}): string => {
|
||||
const pauseIndex = fullText.indexOf(pauseAfter);
|
||||
const preLen =
|
||||
pauseIndex >= 0 ? pauseIndex + pauseAfter.length : fullText.length;
|
||||
|
||||
let typedChars = 0;
|
||||
if (frame < preLen * charFrames) {
|
||||
typedChars = Math.floor(frame / charFrames);
|
||||
} else if (frame < preLen * charFrames + pauseFrames) {
|
||||
typedChars = preLen;
|
||||
} else {
|
||||
const postPhase = frame - preLen * charFrames - pauseFrames;
|
||||
typedChars = Math.min(
|
||||
fullText.length,
|
||||
preLen + Math.floor(postPhase / charFrames),
|
||||
);
|
||||
}
|
||||
return fullText.slice(0, typedChars);
|
||||
};
|
||||
|
||||
const Cursor: React.FC<{
|
||||
frame: number;
|
||||
blinkFrames: number;
|
||||
symbol?: string;
|
||||
}> = ({frame, blinkFrames, symbol = '\u258C'}) => {
|
||||
const opacity = interpolate(
|
||||
frame % blinkFrames,
|
||||
[0, blinkFrames / 2, blinkFrames],
|
||||
[1, 0, 1],
|
||||
{extrapolateLeft: 'clamp', extrapolateRight: 'clamp'},
|
||||
);
|
||||
|
||||
return <span style={{opacity}}>{symbol}</span>;
|
||||
};
|
||||
|
||||
export const MyAnimation = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const {fps} = useVideoConfig();
|
||||
|
||||
const pauseFrames = Math.round(fps * PAUSE_SECONDS);
|
||||
|
||||
const typedText = getTypedText({
|
||||
frame,
|
||||
fullText: FULL_TEXT,
|
||||
pauseAfter: PAUSE_AFTER,
|
||||
charFrames: CHAR_FRAMES,
|
||||
pauseFrames,
|
||||
});
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
backgroundColor: COLOR_BG,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: COLOR_TEXT,
|
||||
fontSize: FONT_SIZE,
|
||||
fontWeight: FONT_WEIGHT,
|
||||
fontFamily: 'sans-serif',
|
||||
}}
|
||||
>
|
||||
<span>{typedText}</span>
|
||||
<Cursor frame={frame} blinkFrames={CURSOR_BLINK_FRAMES} />
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import {loadFont} from '@remotion/google-fonts/Inter';
|
||||
import React from 'react';
|
||||
import {AbsoluteFill, spring, useCurrentFrame, useVideoConfig} from 'remotion';
|
||||
|
||||
/*
|
||||
* Highlight a word in a sentence with a spring-animated wipe effect.
|
||||
*/
|
||||
|
||||
// Ideal composition size: 1280x720
|
||||
|
||||
const COLOR_BG = '#ffffff';
|
||||
const COLOR_TEXT = '#000000';
|
||||
const COLOR_HIGHLIGHT = '#A7C7E7';
|
||||
const FULL_TEXT = 'This is Remotion.';
|
||||
const HIGHLIGHT_WORD = 'Remotion';
|
||||
const FONT_SIZE = 72;
|
||||
const FONT_WEIGHT = 700;
|
||||
const HIGHLIGHT_START_FRAME = 30;
|
||||
const HIGHLIGHT_WIPE_DURATION = 18;
|
||||
|
||||
const {fontFamily} = loadFont();
|
||||
|
||||
const Highlight: React.FC<{
|
||||
word: string;
|
||||
color: string;
|
||||
delay: number;
|
||||
durationInFrames: number;
|
||||
}> = ({word, color, delay, durationInFrames}) => {
|
||||
const frame = useCurrentFrame();
|
||||
const {fps} = useVideoConfig();
|
||||
|
||||
const highlightProgress = spring({
|
||||
fps,
|
||||
frame,
|
||||
config: {damping: 200},
|
||||
delay,
|
||||
durationInFrames,
|
||||
});
|
||||
const scaleX = Math.max(0, Math.min(1, highlightProgress));
|
||||
|
||||
return (
|
||||
<span style={{position: 'relative', display: 'inline-block'}}>
|
||||
<span
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: '50%',
|
||||
height: '1.05em',
|
||||
transform: `translateY(-50%) scaleX(${scaleX})`,
|
||||
transformOrigin: 'left center',
|
||||
backgroundColor: color,
|
||||
borderRadius: '0.18em',
|
||||
zIndex: 0,
|
||||
}}
|
||||
/>
|
||||
<span style={{position: 'relative', zIndex: 1}}>{word}</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export const MyAnimation = () => {
|
||||
const highlightIndex = FULL_TEXT.indexOf(HIGHLIGHT_WORD);
|
||||
const hasHighlight = highlightIndex >= 0;
|
||||
const preText = hasHighlight ? FULL_TEXT.slice(0, highlightIndex) : FULL_TEXT;
|
||||
const postText = hasHighlight
|
||||
? FULL_TEXT.slice(highlightIndex + HIGHLIGHT_WORD.length)
|
||||
: '';
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
backgroundColor: COLOR_BG,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontFamily,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: COLOR_TEXT,
|
||||
fontSize: FONT_SIZE,
|
||||
fontWeight: FONT_WEIGHT,
|
||||
}}
|
||||
>
|
||||
{hasHighlight ? (
|
||||
<>
|
||||
<span>{preText}</span>
|
||||
<Highlight
|
||||
word={HIGHLIGHT_WORD}
|
||||
color={COLOR_HIGHLIGHT}
|
||||
delay={HIGHLIGHT_START_FRAME}
|
||||
durationInFrames={HIGHLIGHT_WIPE_DURATION}
|
||||
/>
|
||||
<span>{postText}</span>
|
||||
</>
|
||||
) : (
|
||||
<span>{FULL_TEXT}</span>
|
||||
)}
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
+1
Submodule builtin-skills/basic-for-all/my-writing-style added at d94826e1cd.
@@ -0,0 +1,158 @@
|
||||
// Complete implementation of condition-based waiting utilities
|
||||
// From: Lace test infrastructure improvements (2025-10-03)
|
||||
// Context: Fixed 15 flaky tests by replacing arbitrary timeouts
|
||||
|
||||
import type { ThreadManager } from '~/threads/thread-manager';
|
||||
import type { LaceEvent, LaceEventType } from '~/threads/types';
|
||||
|
||||
/**
|
||||
* Wait for a specific event type to appear in thread
|
||||
*
|
||||
* @param threadManager - The thread manager to query
|
||||
* @param threadId - Thread to check for events
|
||||
* @param eventType - Type of event to wait for
|
||||
* @param timeoutMs - Maximum time to wait (default 5000ms)
|
||||
* @returns Promise resolving to the first matching event
|
||||
*
|
||||
* Example:
|
||||
* await waitForEvent(threadManager, agentThreadId, 'TOOL_RESULT');
|
||||
*/
|
||||
export function waitForEvent(
|
||||
threadManager: ThreadManager,
|
||||
threadId: string,
|
||||
eventType: LaceEventType,
|
||||
timeoutMs = 5000
|
||||
): Promise<LaceEvent> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
const check = () => {
|
||||
const events = threadManager.getEvents(threadId);
|
||||
const event = events.find((e) => e.type === eventType);
|
||||
|
||||
if (event) {
|
||||
resolve(event);
|
||||
} else if (Date.now() - startTime > timeoutMs) {
|
||||
reject(new Error(`Timeout waiting for ${eventType} event after ${timeoutMs}ms`));
|
||||
} else {
|
||||
setTimeout(check, 10); // Poll every 10ms for efficiency
|
||||
}
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a specific number of events of a given type
|
||||
*
|
||||
* @param threadManager - The thread manager to query
|
||||
* @param threadId - Thread to check for events
|
||||
* @param eventType - Type of event to wait for
|
||||
* @param count - Number of events to wait for
|
||||
* @param timeoutMs - Maximum time to wait (default 5000ms)
|
||||
* @returns Promise resolving to all matching events once count is reached
|
||||
*
|
||||
* Example:
|
||||
* // Wait for 2 AGENT_MESSAGE events (initial response + continuation)
|
||||
* await waitForEventCount(threadManager, agentThreadId, 'AGENT_MESSAGE', 2);
|
||||
*/
|
||||
export function waitForEventCount(
|
||||
threadManager: ThreadManager,
|
||||
threadId: string,
|
||||
eventType: LaceEventType,
|
||||
count: number,
|
||||
timeoutMs = 5000
|
||||
): Promise<LaceEvent[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
const check = () => {
|
||||
const events = threadManager.getEvents(threadId);
|
||||
const matchingEvents = events.filter((e) => e.type === eventType);
|
||||
|
||||
if (matchingEvents.length >= count) {
|
||||
resolve(matchingEvents);
|
||||
} else if (Date.now() - startTime > timeoutMs) {
|
||||
reject(
|
||||
new Error(
|
||||
`Timeout waiting for ${count} ${eventType} events after ${timeoutMs}ms (got ${matchingEvents.length})`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
setTimeout(check, 10);
|
||||
}
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for an event matching a custom predicate
|
||||
* Useful when you need to check event data, not just type
|
||||
*
|
||||
* @param threadManager - The thread manager to query
|
||||
* @param threadId - Thread to check for events
|
||||
* @param predicate - Function that returns true when event matches
|
||||
* @param description - Human-readable description for error messages
|
||||
* @param timeoutMs - Maximum time to wait (default 5000ms)
|
||||
* @returns Promise resolving to the first matching event
|
||||
*
|
||||
* Example:
|
||||
* // Wait for TOOL_RESULT with specific ID
|
||||
* await waitForEventMatch(
|
||||
* threadManager,
|
||||
* agentThreadId,
|
||||
* (e) => e.type === 'TOOL_RESULT' && e.data.id === 'call_123',
|
||||
* 'TOOL_RESULT with id=call_123'
|
||||
* );
|
||||
*/
|
||||
export function waitForEventMatch(
|
||||
threadManager: ThreadManager,
|
||||
threadId: string,
|
||||
predicate: (event: LaceEvent) => boolean,
|
||||
description: string,
|
||||
timeoutMs = 5000
|
||||
): Promise<LaceEvent> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
const check = () => {
|
||||
const events = threadManager.getEvents(threadId);
|
||||
const event = events.find(predicate);
|
||||
|
||||
if (event) {
|
||||
resolve(event);
|
||||
} else if (Date.now() - startTime > timeoutMs) {
|
||||
reject(new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`));
|
||||
} else {
|
||||
setTimeout(check, 10);
|
||||
}
|
||||
};
|
||||
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
// Usage example from actual debugging session:
|
||||
//
|
||||
// BEFORE (flaky):
|
||||
// ---------------
|
||||
// const messagePromise = agent.sendMessage('Execute tools');
|
||||
// await new Promise(r => setTimeout(r, 300)); // Hope tools start in 300ms
|
||||
// agent.abort();
|
||||
// await messagePromise;
|
||||
// await new Promise(r => setTimeout(r, 50)); // Hope results arrive in 50ms
|
||||
// expect(toolResults.length).toBe(2); // Fails randomly
|
||||
//
|
||||
// AFTER (reliable):
|
||||
// ----------------
|
||||
// const messagePromise = agent.sendMessage('Execute tools');
|
||||
// await waitForEventCount(threadManager, threadId, 'TOOL_CALL', 2); // Wait for tools to start
|
||||
// agent.abort();
|
||||
// await messagePromise;
|
||||
// await waitForEventCount(threadManager, threadId, 'TOOL_RESULT', 2); // Wait for results
|
||||
// expect(toolResults.length).toBe(2); // Always succeeds
|
||||
//
|
||||
// Result: 60% pass rate → 100%, 40% faster execution
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bisection script to find which test creates unwanted files/state
|
||||
# Usage: ./find-polluter.sh <file_or_dir_to_check> <test_pattern>
|
||||
# Example: ./find-polluter.sh '.git' 'src/**/*.test.ts'
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Usage: $0 <file_to_check> <test_pattern>"
|
||||
echo "Example: $0 '.git' 'src/**/*.test.ts'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
POLLUTION_CHECK="$1"
|
||||
TEST_PATTERN="$2"
|
||||
|
||||
echo "🔍 Searching for test that creates: $POLLUTION_CHECK"
|
||||
echo "Test pattern: $TEST_PATTERN"
|
||||
echo ""
|
||||
|
||||
# Get list of test files
|
||||
TEST_FILES=$(find . -path "$TEST_PATTERN" | sort)
|
||||
TOTAL=$(echo "$TEST_FILES" | wc -l | tr -d ' ')
|
||||
|
||||
echo "Found $TOTAL test files"
|
||||
echo ""
|
||||
|
||||
COUNT=0
|
||||
for TEST_FILE in $TEST_FILES; do
|
||||
COUNT=$((COUNT + 1))
|
||||
|
||||
# Skip if pollution already exists
|
||||
if [ -e "$POLLUTION_CHECK" ]; then
|
||||
echo "⚠️ Pollution already exists before test $COUNT/$TOTAL"
|
||||
echo " Skipping: $TEST_FILE"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[$COUNT/$TOTAL] Testing: $TEST_FILE"
|
||||
|
||||
# Run the test
|
||||
npm test "$TEST_FILE" > /dev/null 2>&1 || true
|
||||
|
||||
# Check if pollution appeared
|
||||
if [ -e "$POLLUTION_CHECK" ]; then
|
||||
echo ""
|
||||
echo "🎯 FOUND POLLUTER!"
|
||||
echo " Test: $TEST_FILE"
|
||||
echo " Created: $POLLUTION_CHECK"
|
||||
echo ""
|
||||
echo "Pollution details:"
|
||||
ls -la "$POLLUTION_CHECK"
|
||||
echo ""
|
||||
echo "To investigate:"
|
||||
echo " npm test $TEST_FILE # Run just this test"
|
||||
echo " cat $TEST_FILE # Review test code"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✅ No polluter found - all tests clean!"
|
||||
exit 0
|
||||
@@ -0,0 +1,30 @@
|
||||
© 2025 Anthropic, PBC. All rights reserved.
|
||||
|
||||
LICENSE: Use of these materials (including all code, prompts, assets, files,
|
||||
and other components of this Skill) is governed by your agreement with
|
||||
Anthropic regarding use of Anthropic's services. If no separate agreement
|
||||
exists, use is governed by Anthropic's Consumer Terms of Service or
|
||||
Commercial Terms of Service, as applicable:
|
||||
https://www.anthropic.com/legal/consumer-terms
|
||||
https://www.anthropic.com/legal/commercial-terms
|
||||
Your applicable agreement is referred to as the "Agreement." "Services" are
|
||||
as defined in the Agreement.
|
||||
|
||||
ADDITIONAL RESTRICTIONS: Notwithstanding anything in the Agreement to the
|
||||
contrary, users may not:
|
||||
|
||||
- Extract these materials from the Services or retain copies of these
|
||||
materials outside the Services
|
||||
- Reproduce or copy these materials, except for temporary copies created
|
||||
automatically during authorized use of the Services
|
||||
- Create derivative works based on these materials
|
||||
- Distribute, sublicense, or transfer these materials to any third party
|
||||
- Make, offer to sell, sell, or import any inventions embodied in these
|
||||
materials
|
||||
- Reverse engineer, decompile, or disassemble these materials
|
||||
|
||||
The receipt, viewing, or possession of these materials does not convey or
|
||||
imply any license or right beyond those expressly granted above.
|
||||
|
||||
Anthropic retains all right, title, and interest in these materials,
|
||||
including all copyrights, patents, and other intellectual property rights.
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
"""Accept all tracked changes in a DOCX file using LibreOffice.
|
||||
|
||||
Requires LibreOffice (soffice) to be installed.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from office.soffice import get_soffice_env
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
LIBREOFFICE_PROFILE = "/tmp/libreoffice_docx_profile"
|
||||
MACRO_DIR = f"{LIBREOFFICE_PROFILE}/user/basic/Standard"
|
||||
|
||||
ACCEPT_CHANGES_MACRO = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
|
||||
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">
|
||||
Sub AcceptAllTrackedChanges()
|
||||
Dim document As Object
|
||||
Dim dispatcher As Object
|
||||
|
||||
document = ThisComponent.CurrentController.Frame
|
||||
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
|
||||
|
||||
dispatcher.executeDispatch(document, ".uno:AcceptAllTrackedChanges", "", 0, Array())
|
||||
ThisComponent.store()
|
||||
ThisComponent.close(True)
|
||||
End Sub
|
||||
</script:module>"""
|
||||
|
||||
|
||||
def accept_changes(
|
||||
input_file: str,
|
||||
output_file: str,
|
||||
) -> tuple[None, str]:
|
||||
input_path = Path(input_file)
|
||||
output_path = Path(output_file)
|
||||
|
||||
if not input_path.exists():
|
||||
return None, f"Error: Input file not found: {input_file}"
|
||||
|
||||
if not input_path.suffix.lower() == ".docx":
|
||||
return None, f"Error: Input file is not a DOCX file: {input_file}"
|
||||
|
||||
try:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(input_path, output_path)
|
||||
except Exception as e:
|
||||
return None, f"Error: Failed to copy input file to output location: {e}"
|
||||
|
||||
if not _setup_libreoffice_macro():
|
||||
return None, "Error: Failed to setup LibreOffice macro"
|
||||
|
||||
cmd = [
|
||||
"soffice",
|
||||
"--headless",
|
||||
f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}",
|
||||
"--norestore",
|
||||
"vnd.sun.star.script:Standard.Module1.AcceptAllTrackedChanges?language=Basic&location=application",
|
||||
str(output_path.absolute()),
|
||||
]
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
check=False,
|
||||
env=get_soffice_env(),
|
||||
)
|
||||
except subprocess.TimeoutExpired:
|
||||
return (
|
||||
None,
|
||||
f"Successfully accepted all tracked changes: {input_file} -> {output_file}",
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
return None, f"Error: LibreOffice failed: {result.stderr}"
|
||||
|
||||
return (
|
||||
None,
|
||||
f"Successfully accepted all tracked changes: {input_file} -> {output_file}",
|
||||
)
|
||||
|
||||
|
||||
def _setup_libreoffice_macro() -> bool:
|
||||
macro_dir = Path(MACRO_DIR)
|
||||
macro_file = macro_dir / "Module1.xba"
|
||||
|
||||
if macro_file.exists() and "AcceptAllTrackedChanges" in macro_file.read_text():
|
||||
return True
|
||||
|
||||
if not macro_dir.exists():
|
||||
subprocess.run(
|
||||
[
|
||||
"soffice",
|
||||
"--headless",
|
||||
f"-env:UserInstallation=file://{LIBREOFFICE_PROFILE}",
|
||||
"--terminate_after_init",
|
||||
],
|
||||
capture_output=True,
|
||||
timeout=10,
|
||||
check=False,
|
||||
env=get_soffice_env(),
|
||||
)
|
||||
macro_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
try:
|
||||
macro_file.write_text(ACCEPT_CHANGES_MACRO)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to setup LibreOffice macro: {e}")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Accept all tracked changes in a DOCX file"
|
||||
)
|
||||
parser.add_argument("input_file", help="Input DOCX file with tracked changes")
|
||||
parser.add_argument(
|
||||
"output_file", help="Output DOCX file (clean, no tracked changes)"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
_, message = accept_changes(args.input_file, args.output_file)
|
||||
print(message)
|
||||
|
||||
if "Error" in message:
|
||||
raise SystemExit(1)
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
"""Add comments to DOCX documents.
|
||||
|
||||
Usage:
|
||||
python comment.py unpacked/ 0 "Comment text"
|
||||
python comment.py unpacked/ 1 "Reply text" --parent 0
|
||||
|
||||
Text should be pre-escaped XML (e.g., & for &, ’ for smart quotes).
|
||||
|
||||
After running, add markers to document.xml:
|
||||
<w:commentRangeStart w:id="0"/>
|
||||
... commented content ...
|
||||
<w:commentRangeEnd w:id="0"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import random
|
||||
import shutil
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import defusedxml.minidom
|
||||
|
||||
TEMPLATE_DIR = Path(__file__).parent / "templates"
|
||||
NS = {
|
||||
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
|
||||
"w14": "http://schemas.microsoft.com/office/word/2010/wordml",
|
||||
"w15": "http://schemas.microsoft.com/office/word/2012/wordml",
|
||||
"w16cid": "http://schemas.microsoft.com/office/word/2016/wordml/cid",
|
||||
"w16cex": "http://schemas.microsoft.com/office/word/2018/wordml/cex",
|
||||
}
|
||||
|
||||
COMMENT_XML = """\
|
||||
<w:comment w:id="{id}" w:author="{author}" w:date="{date}" w:initials="{initials}">
|
||||
<w:p w14:paraId="{para_id}" w14:textId="77777777">
|
||||
<w:r>
|
||||
<w:rPr><w:rStyle w:val="CommentReference"/></w:rPr>
|
||||
<w:annotationRef/>
|
||||
</w:r>
|
||||
<w:r>
|
||||
<w:rPr>
|
||||
<w:color w:val="000000"/>
|
||||
<w:sz w:val="20"/>
|
||||
<w:szCs w:val="20"/>
|
||||
</w:rPr>
|
||||
<w:t>{text}</w:t>
|
||||
</w:r>
|
||||
</w:p>
|
||||
</w:comment>"""
|
||||
|
||||
COMMENT_MARKER_TEMPLATE = """
|
||||
Add to document.xml (markers must be direct children of w:p, never inside w:r):
|
||||
<w:commentRangeStart w:id="{cid}"/>
|
||||
<w:r>...</w:r>
|
||||
<w:commentRangeEnd w:id="{cid}"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="{cid}"/></w:r>"""
|
||||
|
||||
REPLY_MARKER_TEMPLATE = """
|
||||
Nest markers inside parent {pid}'s markers (markers must be direct children of w:p, never inside w:r):
|
||||
<w:commentRangeStart w:id="{pid}"/><w:commentRangeStart w:id="{cid}"/>
|
||||
<w:r>...</w:r>
|
||||
<w:commentRangeEnd w:id="{cid}"/><w:commentRangeEnd w:id="{pid}"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="{pid}"/></w:r>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="{cid}"/></w:r>"""
|
||||
|
||||
|
||||
def _generate_hex_id() -> str:
|
||||
return f"{random.randint(0, 0x7FFFFFFE):08X}"
|
||||
|
||||
|
||||
SMART_QUOTE_ENTITIES = {
|
||||
"\u201c": "“",
|
||||
"\u201d": "”",
|
||||
"\u2018": "‘",
|
||||
"\u2019": "’",
|
||||
}
|
||||
|
||||
|
||||
def _encode_smart_quotes(text: str) -> str:
|
||||
for char, entity in SMART_QUOTE_ENTITIES.items():
|
||||
text = text.replace(char, entity)
|
||||
return text
|
||||
|
||||
|
||||
def _append_xml(xml_path: Path, root_tag: str, content: str) -> None:
|
||||
dom = defusedxml.minidom.parseString(xml_path.read_text(encoding="utf-8"))
|
||||
root = dom.getElementsByTagName(root_tag)[0]
|
||||
ns_attrs = " ".join(f'xmlns:{k}="{v}"' for k, v in NS.items())
|
||||
wrapper_dom = defusedxml.minidom.parseString(f"<root {ns_attrs}>{content}</root>")
|
||||
for child in wrapper_dom.documentElement.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE:
|
||||
root.appendChild(dom.importNode(child, True))
|
||||
output = _encode_smart_quotes(dom.toxml(encoding="UTF-8").decode("utf-8"))
|
||||
xml_path.write_text(output, encoding="utf-8")
|
||||
|
||||
|
||||
def _find_para_id(comments_path: Path, comment_id: int) -> str | None:
|
||||
dom = defusedxml.minidom.parseString(comments_path.read_text(encoding="utf-8"))
|
||||
for c in dom.getElementsByTagName("w:comment"):
|
||||
if c.getAttribute("w:id") == str(comment_id):
|
||||
for p in c.getElementsByTagName("w:p"):
|
||||
if pid := p.getAttribute("w14:paraId"):
|
||||
return pid
|
||||
return None
|
||||
|
||||
|
||||
def _get_next_rid(rels_path: Path) -> int:
|
||||
dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8"))
|
||||
max_rid = 0
|
||||
for rel in dom.getElementsByTagName("Relationship"):
|
||||
rid = rel.getAttribute("Id")
|
||||
if rid and rid.startswith("rId"):
|
||||
try:
|
||||
max_rid = max(max_rid, int(rid[3:]))
|
||||
except ValueError:
|
||||
pass
|
||||
return max_rid + 1
|
||||
|
||||
|
||||
def _has_relationship(rels_path: Path, target: str) -> bool:
|
||||
dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8"))
|
||||
for rel in dom.getElementsByTagName("Relationship"):
|
||||
if rel.getAttribute("Target") == target:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _has_content_type(ct_path: Path, part_name: str) -> bool:
|
||||
dom = defusedxml.minidom.parseString(ct_path.read_text(encoding="utf-8"))
|
||||
for override in dom.getElementsByTagName("Override"):
|
||||
if override.getAttribute("PartName") == part_name:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _ensure_comment_relationships(unpacked_dir: Path) -> None:
|
||||
rels_path = unpacked_dir / "word" / "_rels" / "document.xml.rels"
|
||||
if not rels_path.exists():
|
||||
return
|
||||
|
||||
if _has_relationship(rels_path, "comments.xml"):
|
||||
return
|
||||
|
||||
dom = defusedxml.minidom.parseString(rels_path.read_text(encoding="utf-8"))
|
||||
root = dom.documentElement
|
||||
next_rid = _get_next_rid(rels_path)
|
||||
|
||||
rels = [
|
||||
(
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
|
||||
"comments.xml",
|
||||
),
|
||||
(
|
||||
"http://schemas.microsoft.com/office/2011/relationships/commentsExtended",
|
||||
"commentsExtended.xml",
|
||||
),
|
||||
(
|
||||
"http://schemas.microsoft.com/office/2016/09/relationships/commentsIds",
|
||||
"commentsIds.xml",
|
||||
),
|
||||
(
|
||||
"http://schemas.microsoft.com/office/2018/08/relationships/commentsExtensible",
|
||||
"commentsExtensible.xml",
|
||||
),
|
||||
]
|
||||
|
||||
for rel_type, target in rels:
|
||||
rel = dom.createElement("Relationship")
|
||||
rel.setAttribute("Id", f"rId{next_rid}")
|
||||
rel.setAttribute("Type", rel_type)
|
||||
rel.setAttribute("Target", target)
|
||||
root.appendChild(rel)
|
||||
next_rid += 1
|
||||
|
||||
rels_path.write_bytes(dom.toxml(encoding="UTF-8"))
|
||||
|
||||
|
||||
def _ensure_comment_content_types(unpacked_dir: Path) -> None:
|
||||
ct_path = unpacked_dir / "[Content_Types].xml"
|
||||
if not ct_path.exists():
|
||||
return
|
||||
|
||||
if _has_content_type(ct_path, "/word/comments.xml"):
|
||||
return
|
||||
|
||||
dom = defusedxml.minidom.parseString(ct_path.read_text(encoding="utf-8"))
|
||||
root = dom.documentElement
|
||||
|
||||
overrides = [
|
||||
(
|
||||
"/word/comments.xml",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml",
|
||||
),
|
||||
(
|
||||
"/word/commentsExtended.xml",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml",
|
||||
),
|
||||
(
|
||||
"/word/commentsIds.xml",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml",
|
||||
),
|
||||
(
|
||||
"/word/commentsExtensible.xml",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtensible+xml",
|
||||
),
|
||||
]
|
||||
|
||||
for part_name, content_type in overrides:
|
||||
override = dom.createElement("Override")
|
||||
override.setAttribute("PartName", part_name)
|
||||
override.setAttribute("ContentType", content_type)
|
||||
root.appendChild(override)
|
||||
|
||||
ct_path.write_bytes(dom.toxml(encoding="UTF-8"))
|
||||
|
||||
|
||||
def add_comment(
|
||||
unpacked_dir: str,
|
||||
comment_id: int,
|
||||
text: str,
|
||||
author: str = "Claude",
|
||||
initials: str = "C",
|
||||
parent_id: int | None = None,
|
||||
) -> tuple[str, str]:
|
||||
word = Path(unpacked_dir) / "word"
|
||||
if not word.exists():
|
||||
return "", f"Error: {word} not found"
|
||||
|
||||
para_id, durable_id = _generate_hex_id(), _generate_hex_id()
|
||||
ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
comments = word / "comments.xml"
|
||||
first_comment = not comments.exists()
|
||||
if first_comment:
|
||||
shutil.copy(TEMPLATE_DIR / "comments.xml", comments)
|
||||
_ensure_comment_relationships(Path(unpacked_dir))
|
||||
_ensure_comment_content_types(Path(unpacked_dir))
|
||||
_append_xml(
|
||||
comments,
|
||||
"w:comments",
|
||||
COMMENT_XML.format(
|
||||
id=comment_id,
|
||||
author=author,
|
||||
date=ts,
|
||||
initials=initials,
|
||||
para_id=para_id,
|
||||
text=text,
|
||||
),
|
||||
)
|
||||
|
||||
ext = word / "commentsExtended.xml"
|
||||
if not ext.exists():
|
||||
shutil.copy(TEMPLATE_DIR / "commentsExtended.xml", ext)
|
||||
if parent_id is not None:
|
||||
parent_para = _find_para_id(comments, parent_id)
|
||||
if not parent_para:
|
||||
return "", f"Error: Parent comment {parent_id} not found"
|
||||
_append_xml(
|
||||
ext,
|
||||
"w15:commentsEx",
|
||||
f'<w15:commentEx w15:paraId="{para_id}" w15:paraIdParent="{parent_para}" w15:done="0"/>',
|
||||
)
|
||||
else:
|
||||
_append_xml(
|
||||
ext,
|
||||
"w15:commentsEx",
|
||||
f'<w15:commentEx w15:paraId="{para_id}" w15:done="0"/>',
|
||||
)
|
||||
|
||||
ids = word / "commentsIds.xml"
|
||||
if not ids.exists():
|
||||
shutil.copy(TEMPLATE_DIR / "commentsIds.xml", ids)
|
||||
_append_xml(
|
||||
ids,
|
||||
"w16cid:commentsIds",
|
||||
f'<w16cid:commentId w16cid:paraId="{para_id}" w16cid:durableId="{durable_id}"/>',
|
||||
)
|
||||
|
||||
extensible = word / "commentsExtensible.xml"
|
||||
if not extensible.exists():
|
||||
shutil.copy(TEMPLATE_DIR / "commentsExtensible.xml", extensible)
|
||||
_append_xml(
|
||||
extensible,
|
||||
"w16cex:commentsExtensible",
|
||||
f'<w16cex:commentExtensible w16cex:durableId="{durable_id}" w16cex:dateUtc="{ts}"/>',
|
||||
)
|
||||
|
||||
action = "reply" if parent_id is not None else "comment"
|
||||
return para_id, f"Added {action} {comment_id} (para_id={para_id})"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
p = argparse.ArgumentParser(description="Add comments to DOCX documents")
|
||||
p.add_argument("unpacked_dir", help="Unpacked DOCX directory")
|
||||
p.add_argument("comment_id", type=int, help="Comment ID (must be unique)")
|
||||
p.add_argument("text", help="Comment text")
|
||||
p.add_argument("--author", default="Claude", help="Author name")
|
||||
p.add_argument("--initials", default="C", help="Author initials")
|
||||
p.add_argument("--parent", type=int, help="Parent comment ID (for replies)")
|
||||
args = p.parse_args()
|
||||
|
||||
para_id, msg = add_comment(
|
||||
args.unpacked_dir,
|
||||
args.comment_id,
|
||||
args.text,
|
||||
args.author,
|
||||
args.initials,
|
||||
args.parent,
|
||||
)
|
||||
print(msg)
|
||||
if "Error" in msg:
|
||||
sys.exit(1)
|
||||
cid = args.comment_id
|
||||
if args.parent is not None:
|
||||
print(REPLY_MARKER_TEMPLATE.format(pid=args.parent, cid=cid))
|
||||
else:
|
||||
print(COMMENT_MARKER_TEMPLATE.format(cid=cid))
|
||||
Whitespace-only changes.
@@ -0,0 +1,199 @@
|
||||
"""Merge adjacent runs with identical formatting in DOCX.
|
||||
|
||||
Merges adjacent <w:r> elements that have identical <w:rPr> properties.
|
||||
Works on runs in paragraphs and inside tracked changes (<w:ins>, <w:del>).
|
||||
|
||||
Also:
|
||||
- Removes rsid attributes from runs (revision metadata that doesn't affect rendering)
|
||||
- Removes proofErr elements (spell/grammar markers that block merging)
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import defusedxml.minidom
|
||||
|
||||
|
||||
def merge_runs(input_dir: str) -> tuple[int, str]:
|
||||
doc_xml = Path(input_dir) / "word" / "document.xml"
|
||||
|
||||
if not doc_xml.exists():
|
||||
return 0, f"Error: {doc_xml} not found"
|
||||
|
||||
try:
|
||||
dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8"))
|
||||
root = dom.documentElement
|
||||
|
||||
_remove_elements(root, "proofErr")
|
||||
_strip_run_rsid_attrs(root)
|
||||
|
||||
containers = {run.parentNode for run in _find_elements(root, "r")}
|
||||
|
||||
merge_count = 0
|
||||
for container in containers:
|
||||
merge_count += _merge_runs_in(container)
|
||||
|
||||
doc_xml.write_bytes(dom.toxml(encoding="UTF-8"))
|
||||
return merge_count, f"Merged {merge_count} runs"
|
||||
|
||||
except Exception as e:
|
||||
return 0, f"Error: {e}"
|
||||
|
||||
|
||||
|
||||
|
||||
def _find_elements(root, tag: str) -> list:
|
||||
results = []
|
||||
|
||||
def traverse(node):
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
name = node.localName or node.tagName
|
||||
if name == tag or name.endswith(f":{tag}"):
|
||||
results.append(node)
|
||||
for child in node.childNodes:
|
||||
traverse(child)
|
||||
|
||||
traverse(root)
|
||||
return results
|
||||
|
||||
|
||||
def _get_child(parent, tag: str):
|
||||
for child in parent.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE:
|
||||
name = child.localName or child.tagName
|
||||
if name == tag or name.endswith(f":{tag}"):
|
||||
return child
|
||||
return None
|
||||
|
||||
|
||||
def _get_children(parent, tag: str) -> list:
|
||||
results = []
|
||||
for child in parent.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE:
|
||||
name = child.localName or child.tagName
|
||||
if name == tag or name.endswith(f":{tag}"):
|
||||
results.append(child)
|
||||
return results
|
||||
|
||||
|
||||
def _is_adjacent(elem1, elem2) -> bool:
|
||||
node = elem1.nextSibling
|
||||
while node:
|
||||
if node == elem2:
|
||||
return True
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
return False
|
||||
if node.nodeType == node.TEXT_NODE and node.data.strip():
|
||||
return False
|
||||
node = node.nextSibling
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
def _remove_elements(root, tag: str):
|
||||
for elem in _find_elements(root, tag):
|
||||
if elem.parentNode:
|
||||
elem.parentNode.removeChild(elem)
|
||||
|
||||
|
||||
def _strip_run_rsid_attrs(root):
|
||||
for run in _find_elements(root, "r"):
|
||||
for attr in list(run.attributes.values()):
|
||||
if "rsid" in attr.name.lower():
|
||||
run.removeAttribute(attr.name)
|
||||
|
||||
|
||||
|
||||
|
||||
def _merge_runs_in(container) -> int:
|
||||
merge_count = 0
|
||||
run = _first_child_run(container)
|
||||
|
||||
while run:
|
||||
while True:
|
||||
next_elem = _next_element_sibling(run)
|
||||
if next_elem and _is_run(next_elem) and _can_merge(run, next_elem):
|
||||
_merge_run_content(run, next_elem)
|
||||
container.removeChild(next_elem)
|
||||
merge_count += 1
|
||||
else:
|
||||
break
|
||||
|
||||
_consolidate_text(run)
|
||||
run = _next_sibling_run(run)
|
||||
|
||||
return merge_count
|
||||
|
||||
|
||||
def _first_child_run(container):
|
||||
for child in container.childNodes:
|
||||
if child.nodeType == child.ELEMENT_NODE and _is_run(child):
|
||||
return child
|
||||
return None
|
||||
|
||||
|
||||
def _next_element_sibling(node):
|
||||
sibling = node.nextSibling
|
||||
while sibling:
|
||||
if sibling.nodeType == sibling.ELEMENT_NODE:
|
||||
return sibling
|
||||
sibling = sibling.nextSibling
|
||||
return None
|
||||
|
||||
|
||||
def _next_sibling_run(node):
|
||||
sibling = node.nextSibling
|
||||
while sibling:
|
||||
if sibling.nodeType == sibling.ELEMENT_NODE:
|
||||
if _is_run(sibling):
|
||||
return sibling
|
||||
sibling = sibling.nextSibling
|
||||
return None
|
||||
|
||||
|
||||
def _is_run(node) -> bool:
|
||||
name = node.localName or node.tagName
|
||||
return name == "r" or name.endswith(":r")
|
||||
|
||||
|
||||
def _can_merge(run1, run2) -> bool:
|
||||
rpr1 = _get_child(run1, "rPr")
|
||||
rpr2 = _get_child(run2, "rPr")
|
||||
|
||||
if (rpr1 is None) != (rpr2 is None):
|
||||
return False
|
||||
if rpr1 is None:
|
||||
return True
|
||||
return rpr1.toxml() == rpr2.toxml()
|
||||
|
||||
|
||||
def _merge_run_content(target, source):
|
||||
for child in list(source.childNodes):
|
||||
if child.nodeType == child.ELEMENT_NODE:
|
||||
name = child.localName or child.tagName
|
||||
if name != "rPr" and not name.endswith(":rPr"):
|
||||
target.appendChild(child)
|
||||
|
||||
|
||||
def _consolidate_text(run):
|
||||
t_elements = _get_children(run, "t")
|
||||
|
||||
for i in range(len(t_elements) - 1, 0, -1):
|
||||
curr, prev = t_elements[i], t_elements[i - 1]
|
||||
|
||||
if _is_adjacent(prev, curr):
|
||||
prev_text = prev.firstChild.data if prev.firstChild else ""
|
||||
curr_text = curr.firstChild.data if curr.firstChild else ""
|
||||
merged = prev_text + curr_text
|
||||
|
||||
if prev.firstChild:
|
||||
prev.firstChild.data = merged
|
||||
else:
|
||||
prev.appendChild(run.ownerDocument.createTextNode(merged))
|
||||
|
||||
if merged.startswith(" ") or merged.endswith(" "):
|
||||
prev.setAttribute("xml:space", "preserve")
|
||||
elif prev.hasAttribute("xml:space"):
|
||||
prev.removeAttribute("xml:space")
|
||||
|
||||
run.removeChild(curr)
|
||||
@@ -0,0 +1,197 @@
|
||||
"""Simplify tracked changes by merging adjacent w:ins or w:del elements.
|
||||
|
||||
Merges adjacent <w:ins> elements from the same author into a single element.
|
||||
Same for <w:del> elements. This makes heavily-redlined documents easier to
|
||||
work with by reducing the number of tracked change wrappers.
|
||||
|
||||
Rules:
|
||||
- Only merges w:ins with w:ins, w:del with w:del (same element type)
|
||||
- Only merges if same author (ignores timestamp differences)
|
||||
- Only merges if truly adjacent (only whitespace between them)
|
||||
"""
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
import defusedxml.minidom
|
||||
|
||||
WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
|
||||
|
||||
def simplify_redlines(input_dir: str) -> tuple[int, str]:
|
||||
doc_xml = Path(input_dir) / "word" / "document.xml"
|
||||
|
||||
if not doc_xml.exists():
|
||||
return 0, f"Error: {doc_xml} not found"
|
||||
|
||||
try:
|
||||
dom = defusedxml.minidom.parseString(doc_xml.read_text(encoding="utf-8"))
|
||||
root = dom.documentElement
|
||||
|
||||
merge_count = 0
|
||||
|
||||
containers = _find_elements(root, "p") + _find_elements(root, "tc")
|
||||
|
||||
for container in containers:
|
||||
merge_count += _merge_tracked_changes_in(container, "ins")
|
||||
merge_count += _merge_tracked_changes_in(container, "del")
|
||||
|
||||
doc_xml.write_bytes(dom.toxml(encoding="UTF-8"))
|
||||
return merge_count, f"Simplified {merge_count} tracked changes"
|
||||
|
||||
except Exception as e:
|
||||
return 0, f"Error: {e}"
|
||||
|
||||
|
||||
def _merge_tracked_changes_in(container, tag: str) -> int:
|
||||
merge_count = 0
|
||||
|
||||
tracked = [
|
||||
child
|
||||
for child in container.childNodes
|
||||
if child.nodeType == child.ELEMENT_NODE and _is_element(child, tag)
|
||||
]
|
||||
|
||||
if len(tracked) < 2:
|
||||
return 0
|
||||
|
||||
i = 0
|
||||
while i < len(tracked) - 1:
|
||||
curr = tracked[i]
|
||||
next_elem = tracked[i + 1]
|
||||
|
||||
if _can_merge_tracked(curr, next_elem):
|
||||
_merge_tracked_content(curr, next_elem)
|
||||
container.removeChild(next_elem)
|
||||
tracked.pop(i + 1)
|
||||
merge_count += 1
|
||||
else:
|
||||
i += 1
|
||||
|
||||
return merge_count
|
||||
|
||||
|
||||
def _is_element(node, tag: str) -> bool:
|
||||
name = node.localName or node.tagName
|
||||
return name == tag or name.endswith(f":{tag}")
|
||||
|
||||
|
||||
def _get_author(elem) -> str:
|
||||
author = elem.getAttribute("w:author")
|
||||
if not author:
|
||||
for attr in elem.attributes.values():
|
||||
if attr.localName == "author" or attr.name.endswith(":author"):
|
||||
return attr.value
|
||||
return author
|
||||
|
||||
|
||||
def _can_merge_tracked(elem1, elem2) -> bool:
|
||||
if _get_author(elem1) != _get_author(elem2):
|
||||
return False
|
||||
|
||||
node = elem1.nextSibling
|
||||
while node and node != elem2:
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
return False
|
||||
if node.nodeType == node.TEXT_NODE and node.data.strip():
|
||||
return False
|
||||
node = node.nextSibling
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _merge_tracked_content(target, source):
|
||||
while source.firstChild:
|
||||
child = source.firstChild
|
||||
source.removeChild(child)
|
||||
target.appendChild(child)
|
||||
|
||||
|
||||
def _find_elements(root, tag: str) -> list:
|
||||
results = []
|
||||
|
||||
def traverse(node):
|
||||
if node.nodeType == node.ELEMENT_NODE:
|
||||
name = node.localName or node.tagName
|
||||
if name == tag or name.endswith(f":{tag}"):
|
||||
results.append(node)
|
||||
for child in node.childNodes:
|
||||
traverse(child)
|
||||
|
||||
traverse(root)
|
||||
return results
|
||||
|
||||
|
||||
def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
|
||||
if not doc_xml_path.exists():
|
||||
return {}
|
||||
|
||||
try:
|
||||
tree = ET.parse(doc_xml_path)
|
||||
root = tree.getroot()
|
||||
except ET.ParseError:
|
||||
return {}
|
||||
|
||||
namespaces = {"w": WORD_NS}
|
||||
author_attr = f"{{{WORD_NS}}}author"
|
||||
|
||||
authors: dict[str, int] = {}
|
||||
for tag in ["ins", "del"]:
|
||||
for elem in root.findall(f".//w:{tag}", namespaces):
|
||||
author = elem.get(author_attr)
|
||||
if author:
|
||||
authors[author] = authors.get(author, 0) + 1
|
||||
|
||||
return authors
|
||||
|
||||
|
||||
def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
|
||||
try:
|
||||
with zipfile.ZipFile(docx_path, "r") as zf:
|
||||
if "word/document.xml" not in zf.namelist():
|
||||
return {}
|
||||
with zf.open("word/document.xml") as f:
|
||||
tree = ET.parse(f)
|
||||
root = tree.getroot()
|
||||
|
||||
namespaces = {"w": WORD_NS}
|
||||
author_attr = f"{{{WORD_NS}}}author"
|
||||
|
||||
authors: dict[str, int] = {}
|
||||
for tag in ["ins", "del"]:
|
||||
for elem in root.findall(f".//w:{tag}", namespaces):
|
||||
author = elem.get(author_attr)
|
||||
if author:
|
||||
authors[author] = authors.get(author, 0) + 1
|
||||
return authors
|
||||
except (zipfile.BadZipFile, ET.ParseError):
|
||||
return {}
|
||||
|
||||
|
||||
def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str:
|
||||
modified_xml = modified_dir / "word" / "document.xml"
|
||||
modified_authors = get_tracked_change_authors(modified_xml)
|
||||
|
||||
if not modified_authors:
|
||||
return default
|
||||
|
||||
original_authors = _get_authors_from_docx(original_docx)
|
||||
|
||||
new_changes: dict[str, int] = {}
|
||||
for author, count in modified_authors.items():
|
||||
original_count = original_authors.get(author, 0)
|
||||
diff = count - original_count
|
||||
if diff > 0:
|
||||
new_changes[author] = diff
|
||||
|
||||
if not new_changes:
|
||||
return default
|
||||
|
||||
if len(new_changes) == 1:
|
||||
return next(iter(new_changes))
|
||||
|
||||
raise ValueError(
|
||||
f"Multiple authors added new changes: {new_changes}. "
|
||||
"Cannot infer which author to validate."
|
||||
)
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
"""Pack a directory into a DOCX, PPTX, or XLSX file.
|
||||
|
||||
Validates with auto-repair, condenses XML formatting, and creates the Office file.
|
||||
|
||||
Usage:
|
||||
python pack.py <input_directory> <output_file> [--original <file>] [--validate true|false]
|
||||
|
||||
Examples:
|
||||
python pack.py unpacked/ output.docx --original input.docx
|
||||
python pack.py unpacked/ output.pptx --validate false
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
import defusedxml.minidom
|
||||
|
||||
from validators import DOCXSchemaValidator, PPTXSchemaValidator, RedliningValidator
|
||||
|
||||
def pack(
|
||||
input_directory: str,
|
||||
output_file: str,
|
||||
original_file: str | None = None,
|
||||
validate: bool = True,
|
||||
infer_author_func=None,
|
||||
) -> tuple[None, str]:
|
||||
input_dir = Path(input_directory)
|
||||
output_path = Path(output_file)
|
||||
suffix = output_path.suffix.lower()
|
||||
|
||||
if not input_dir.is_dir():
|
||||
return None, f"Error: {input_dir} is not a directory"
|
||||
|
||||
if suffix not in {".docx", ".pptx", ".xlsx"}:
|
||||
return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file"
|
||||
|
||||
if validate and original_file:
|
||||
original_path = Path(original_file)
|
||||
if original_path.exists():
|
||||
success, output = _run_validation(
|
||||
input_dir, original_path, suffix, infer_author_func
|
||||
)
|
||||
if output:
|
||||
print(output)
|
||||
if not success:
|
||||
return None, f"Error: Validation failed for {input_dir}"
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_content_dir = Path(temp_dir) / "content"
|
||||
shutil.copytree(input_dir, temp_content_dir)
|
||||
|
||||
for pattern in ["*.xml", "*.rels"]:
|
||||
for xml_file in temp_content_dir.rglob(pattern):
|
||||
_condense_xml(xml_file)
|
||||
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
||||
for f in temp_content_dir.rglob("*"):
|
||||
if f.is_file():
|
||||
zf.write(f, f.relative_to(temp_content_dir))
|
||||
|
||||
return None, f"Successfully packed {input_dir} to {output_file}"
|
||||
|
||||
|
||||
def _run_validation(
|
||||
unpacked_dir: Path,
|
||||
original_file: Path,
|
||||
suffix: str,
|
||||
infer_author_func=None,
|
||||
) -> tuple[bool, str | None]:
|
||||
output_lines = []
|
||||
validators = []
|
||||
|
||||
if suffix == ".docx":
|
||||
author = "Claude"
|
||||
if infer_author_func:
|
||||
try:
|
||||
author = infer_author_func(unpacked_dir, original_file)
|
||||
except ValueError as e:
|
||||
print(f"Warning: {e} Using default author 'Claude'.", file=sys.stderr)
|
||||
|
||||
validators = [
|
||||
DOCXSchemaValidator(unpacked_dir, original_file),
|
||||
RedliningValidator(unpacked_dir, original_file, author=author),
|
||||
]
|
||||
elif suffix == ".pptx":
|
||||
validators = [PPTXSchemaValidator(unpacked_dir, original_file)]
|
||||
|
||||
if not validators:
|
||||
return True, None
|
||||
|
||||
total_repairs = sum(v.repair() for v in validators)
|
||||
if total_repairs:
|
||||
output_lines.append(f"Auto-repaired {total_repairs} issue(s)")
|
||||
|
||||
success = all(v.validate() for v in validators)
|
||||
|
||||
if success:
|
||||
output_lines.append("All validations PASSED!")
|
||||
|
||||
return success, "\n".join(output_lines) if output_lines else None
|
||||
|
||||
|
||||
def _condense_xml(xml_file: Path) -> None:
|
||||
try:
|
||||
with open(xml_file, encoding="utf-8") as f:
|
||||
dom = defusedxml.minidom.parse(f)
|
||||
|
||||
for element in dom.getElementsByTagName("*"):
|
||||
if element.tagName.endswith(":t"):
|
||||
continue
|
||||
|
||||
for child in list(element.childNodes):
|
||||
if (
|
||||
child.nodeType == child.TEXT_NODE
|
||||
and child.nodeValue
|
||||
and child.nodeValue.strip() == ""
|
||||
) or child.nodeType == child.COMMENT_NODE:
|
||||
element.removeChild(child)
|
||||
|
||||
xml_file.write_bytes(dom.toxml(encoding="UTF-8"))
|
||||
except Exception as e:
|
||||
print(f"ERROR: Failed to parse {xml_file.name}: {e}", file=sys.stderr)
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Pack a directory into a DOCX, PPTX, or XLSX file"
|
||||
)
|
||||
parser.add_argument("input_directory", help="Unpacked Office document directory")
|
||||
parser.add_argument("output_file", help="Output Office file (.docx/.pptx/.xlsx)")
|
||||
parser.add_argument(
|
||||
"--original",
|
||||
help="Original file for validation comparison",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--validate",
|
||||
type=lambda x: x.lower() == "true",
|
||||
default=True,
|
||||
metavar="true|false",
|
||||
help="Run validation with auto-repair (default: true)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
_, message = pack(
|
||||
args.input_directory,
|
||||
args.output_file,
|
||||
original_file=args.original,
|
||||
validate=args.validate,
|
||||
)
|
||||
print(message)
|
||||
|
||||
if "Error" in message:
|
||||
sys.exit(1)
|
||||
+1499
File diff suppressed because it is too large.
Load diff
+146
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
xmlns="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
|
||||
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
schemaLocation="dml-main.xsd"/>
|
||||
<xsd:complexType name="CT_ShapeNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
|
||||
/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Shape">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_ConnectorNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Connector">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_PictureNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Picture">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GraphicFrameNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GraphicFrame">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvGraphicFramePr" type="CT_GraphicFrameNonVisual" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GroupShapeNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GroupShape">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="sp" type="CT_Shape"/>
|
||||
<xsd:element name="grpSp" type="CT_GroupShape"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
|
||||
<xsd:element name="cxnSp" type="CT_Connector"/>
|
||||
<xsd:element name="pic" type="CT_Picture"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="EG_ObjectChoices">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="sp" type="CT_Shape"/>
|
||||
<xsd:element name="grpSp" type="CT_GroupShape"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
|
||||
<xsd:element name="cxnSp" type="CT_Connector"/>
|
||||
<xsd:element name="pic" type="CT_Picture"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:group>
|
||||
<xsd:simpleType name="ST_MarkerCoordinate">
|
||||
<xsd:restriction base="xsd:double">
|
||||
<xsd:minInclusive value="0.0"/>
|
||||
<xsd:maxInclusive value="1.0"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_Marker">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="x" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="y" type="ST_MarkerCoordinate" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_RelSizeAnchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="from" type="CT_Marker"/>
|
||||
<xsd:element name="to" type="CT_Marker"/>
|
||||
<xsd:group ref="EG_ObjectChoices"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_AbsSizeAnchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="from" type="CT_Marker"/>
|
||||
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
|
||||
<xsd:group ref="EG_ObjectChoices"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="EG_Anchor">
|
||||
<xsd:choice>
|
||||
<xsd:element name="relSizeAnchor" type="CT_RelSizeAnchor"/>
|
||||
<xsd:element name="absSizeAnchor" type="CT_AbsSizeAnchor"/>
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
<xsd:complexType name="CT_Drawing">
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
+1085
File diff suppressed because it is too large.
Load diff
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
schemaLocation="dml-main.xsd"/>
|
||||
<xsd:element name="lockedCanvas" type="a:CT_GvmlGroupShape"/>
|
||||
</xsd:schema>
|
||||
+3081
File diff suppressed because it is too large.
Load diff
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.openxmlformats.org/drawingml/2006/picture"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" elementFormDefault="qualified"
|
||||
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/picture">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
schemaLocation="dml-main.xsd"/>
|
||||
<xsd:complexType name="CT_PictureNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Picture">
|
||||
<xsd:sequence minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="pic" type="CT_Picture"/>
|
||||
</xsd:schema>
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
xmlns="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
|
||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
schemaLocation="dml-main.xsd"/>
|
||||
<xsd:import schemaLocation="shared-relationshipReference.xsd"
|
||||
namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>
|
||||
<xsd:element name="from" type="CT_Marker"/>
|
||||
<xsd:element name="to" type="CT_Marker"/>
|
||||
<xsd:complexType name="CT_AnchorClientData">
|
||||
<xsd:attribute name="fLocksWithSheet" type="xsd:boolean" use="optional" default="true"/>
|
||||
<xsd:attribute name="fPrintsWithSheet" type="xsd:boolean" use="optional" default="true"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_ShapeNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1" maxOccurs="1"
|
||||
/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Shape">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="textlink" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fLocksText" type="xsd:boolean" use="optional" default="true"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_ConnectorNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Connector">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_PictureNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Picture">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="blipFill" type="a:CT_BlipFillProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional" default=""/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GraphicalObjectFrameNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GraphicalObjectFrame">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvGraphicFramePr" type="CT_GraphicalObjectFrameNonVisual" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="macro" type="xsd:string" use="optional"/>
|
||||
<xsd:attribute name="fPublished" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GroupShapeNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GroupShape">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="sp" type="CT_Shape"/>
|
||||
<xsd:element name="grpSp" type="CT_GroupShape"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
|
||||
<xsd:element name="cxnSp" type="CT_Connector"/>
|
||||
<xsd:element name="pic" type="CT_Picture"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="EG_ObjectChoices">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="sp" type="CT_Shape"/>
|
||||
<xsd:element name="grpSp" type="CT_GroupShape"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
|
||||
<xsd:element name="cxnSp" type="CT_Connector"/>
|
||||
<xsd:element name="pic" type="CT_Picture"/>
|
||||
<xsd:element name="contentPart" type="CT_Rel"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:group>
|
||||
<xsd:complexType name="CT_Rel">
|
||||
<xsd:attribute ref="r:id" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_ColID">
|
||||
<xsd:restriction base="xsd:int">
|
||||
<xsd:minInclusive value="0"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_RowID">
|
||||
<xsd:restriction base="xsd:int">
|
||||
<xsd:minInclusive value="0"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_Marker">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="col" type="ST_ColID"/>
|
||||
<xsd:element name="colOff" type="a:ST_Coordinate"/>
|
||||
<xsd:element name="row" type="ST_RowID"/>
|
||||
<xsd:element name="rowOff" type="a:ST_Coordinate"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_EditAs">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="twoCell"/>
|
||||
<xsd:enumeration value="oneCell"/>
|
||||
<xsd:enumeration value="absolute"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_TwoCellAnchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="from" type="CT_Marker"/>
|
||||
<xsd:element name="to" type="CT_Marker"/>
|
||||
<xsd:group ref="EG_ObjectChoices"/>
|
||||
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="editAs" type="ST_EditAs" use="optional" default="twoCell"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_OneCellAnchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="from" type="CT_Marker"/>
|
||||
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
|
||||
<xsd:group ref="EG_ObjectChoices"/>
|
||||
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_AbsoluteAnchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="pos" type="a:CT_Point2D"/>
|
||||
<xsd:element name="ext" type="a:CT_PositiveSize2D"/>
|
||||
<xsd:group ref="EG_ObjectChoices"/>
|
||||
<xsd:element name="clientData" type="CT_AnchorClientData" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="EG_Anchor">
|
||||
<xsd:choice>
|
||||
<xsd:element name="twoCellAnchor" type="CT_TwoCellAnchor"/>
|
||||
<xsd:element name="oneCellAnchor" type="CT_OneCellAnchor"/>
|
||||
<xsd:element name="absoluteAnchor" type="CT_AbsoluteAnchor"/>
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
<xsd:complexType name="CT_Drawing">
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="EG_Anchor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="wsDr" type="CT_Drawing"/>
|
||||
</xsd:schema>
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
xmlns:dpct="http://schemas.openxmlformats.org/drawingml/2006/picture"
|
||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
xmlns="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
|
||||
targetNamespace="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/main"
|
||||
schemaLocation="dml-main.xsd"/>
|
||||
<xsd:import schemaLocation="wml.xsd"
|
||||
namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/drawingml/2006/picture"
|
||||
schemaLocation="dml-picture.xsd"/>
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
schemaLocation="shared-relationshipReference.xsd"/>
|
||||
<xsd:complexType name="CT_EffectExtent">
|
||||
<xsd:attribute name="l" type="a:ST_Coordinate" use="required"/>
|
||||
<xsd:attribute name="t" type="a:ST_Coordinate" use="required"/>
|
||||
<xsd:attribute name="r" type="a:ST_Coordinate" use="required"/>
|
||||
<xsd:attribute name="b" type="a:ST_Coordinate" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_WrapDistance">
|
||||
<xsd:restriction base="xsd:unsignedInt"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_Inline">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
||||
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_WrapText">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="bothSides"/>
|
||||
<xsd:enumeration value="left"/>
|
||||
<xsd:enumeration value="right"/>
|
||||
<xsd:enumeration value="largest"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_WrapPath">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="start" type="a:CT_Point2D" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="lineTo" type="a:CT_Point2D" minOccurs="2" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="edited" type="xsd:boolean" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WrapNone"/>
|
||||
<xsd:complexType name="CT_WrapSquare">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
||||
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WrapTight">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
||||
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WrapThrough">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="wrapPolygon" type="CT_WrapPath" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="wrapText" type="ST_WrapText" use="required"/>
|
||||
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WrapTopBottom">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:group name="EG_WrapType">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="wrapNone" type="CT_WrapNone" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="wrapSquare" type="CT_WrapSquare" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="wrapTight" type="CT_WrapTight" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="wrapThrough" type="CT_WrapThrough" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="wrapTopAndBottom" type="CT_WrapTopBottom" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:group>
|
||||
<xsd:simpleType name="ST_PositionOffset">
|
||||
<xsd:restriction base="xsd:int"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_AlignH">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="left"/>
|
||||
<xsd:enumeration value="right"/>
|
||||
<xsd:enumeration value="center"/>
|
||||
<xsd:enumeration value="inside"/>
|
||||
<xsd:enumeration value="outside"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_RelFromH">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="margin"/>
|
||||
<xsd:enumeration value="page"/>
|
||||
<xsd:enumeration value="column"/>
|
||||
<xsd:enumeration value="character"/>
|
||||
<xsd:enumeration value="leftMargin"/>
|
||||
<xsd:enumeration value="rightMargin"/>
|
||||
<xsd:enumeration value="insideMargin"/>
|
||||
<xsd:enumeration value="outsideMargin"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_PosH">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="align" type="ST_AlignH" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="relativeFrom" type="ST_RelFromH" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_AlignV">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="top"/>
|
||||
<xsd:enumeration value="bottom"/>
|
||||
<xsd:enumeration value="center"/>
|
||||
<xsd:enumeration value="inside"/>
|
||||
<xsd:enumeration value="outside"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_RelFromV">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="margin"/>
|
||||
<xsd:enumeration value="page"/>
|
||||
<xsd:enumeration value="paragraph"/>
|
||||
<xsd:enumeration value="line"/>
|
||||
<xsd:enumeration value="topMargin"/>
|
||||
<xsd:enumeration value="bottomMargin"/>
|
||||
<xsd:enumeration value="insideMargin"/>
|
||||
<xsd:enumeration value="outsideMargin"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_PosV">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="align" type="ST_AlignV" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="posOffset" type="ST_PositionOffset" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="relativeFrom" type="ST_RelFromV" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Anchor">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="simplePos" type="a:CT_Point2D"/>
|
||||
<xsd:element name="positionH" type="CT_PosH"/>
|
||||
<xsd:element name="positionV" type="CT_PosV"/>
|
||||
<xsd:element name="extent" type="a:CT_PositiveSize2D"/>
|
||||
<xsd:element name="effectExtent" type="CT_EffectExtent" minOccurs="0"/>
|
||||
<xsd:group ref="EG_WrapType"/>
|
||||
<xsd:element name="docPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"
|
||||
minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="distT" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distB" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distL" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="distR" type="ST_WrapDistance" use="optional"/>
|
||||
<xsd:attribute name="simplePos" type="xsd:boolean"/>
|
||||
<xsd:attribute name="relativeHeight" type="xsd:unsignedInt" use="required"/>
|
||||
<xsd:attribute name="behindDoc" type="xsd:boolean" use="required"/>
|
||||
<xsd:attribute name="locked" type="xsd:boolean" use="required"/>
|
||||
<xsd:attribute name="layoutInCell" type="xsd:boolean" use="required"/>
|
||||
<xsd:attribute name="hidden" type="xsd:boolean" use="optional"/>
|
||||
<xsd:attribute name="allowOverlap" type="xsd:boolean" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_TxbxContent">
|
||||
<xsd:group ref="w:EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_TextboxInfo">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="txbxContent" type="CT_TxbxContent" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:unsignedShort" use="optional" default="0"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_LinkedTextboxInformation">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:unsignedShort" use="required"/>
|
||||
<xsd:attribute name="seq" type="xsd:unsignedShort" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WordprocessingShape">
|
||||
<xsd:sequence minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
<xsd:element name="cNvCnPr" type="a:CT_NonVisualConnectorProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:choice>
|
||||
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="txbx" type="CT_TextboxInfo" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="linkedTxbx" type="CT_LinkedTextboxInformation" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
</xsd:choice>
|
||||
<xsd:element name="bodyPr" type="a:CT_TextBodyProperties" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="normalEastAsianFlow" type="xsd:boolean" use="optional" default="false"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_GraphicFrame">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="cNvFrPr" type="a:CT_NonVisualGraphicFrameProperties" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element ref="a:graphic" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WordprocessingContentPartNonVisual">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="cNvContentPartPr" type="a:CT_NonVisualContentPartProperties" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WordprocessingContentPart">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="nvContentPartPr" type="CT_WordprocessingContentPartNonVisual" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="xfrm" type="a:CT_Transform2D" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional"/>
|
||||
<xsd:attribute ref="r:id" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WordprocessingGroup">
|
||||
<xsd:sequence minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps" minOccurs="1"
|
||||
maxOccurs="1"/>
|
||||
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element ref="wsp"/>
|
||||
<xsd:element name="grpSp" type="CT_WordprocessingGroup"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
|
||||
<xsd:element ref="dpct:pic"/>
|
||||
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
|
||||
</xsd:choice>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_WordprocessingCanvas">
|
||||
<xsd:sequence minOccurs="1" maxOccurs="1">
|
||||
<xsd:element name="bg" type="a:CT_BackgroundFormatting" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="whole" type="a:CT_WholeE2oFormatting" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element ref="wsp"/>
|
||||
<xsd:element ref="dpct:pic"/>
|
||||
<xsd:element name="contentPart" type="CT_WordprocessingContentPart"/>
|
||||
<xsd:element ref="wgp"/>
|
||||
<xsd:element name="graphicFrame" type="CT_GraphicFrame"/>
|
||||
</xsd:choice>
|
||||
<xsd:element name="extLst" type="a:CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="wpc" type="CT_WordprocessingCanvas"/>
|
||||
<xsd:element name="wgp" type="CT_WordprocessingGroup"/>
|
||||
<xsd:element name="wsp" type="CT_WordprocessingShape"/>
|
||||
<xsd:element name="inline" type="CT_Inline"/>
|
||||
<xsd:element name="anchor" type="CT_Anchor"/>
|
||||
</xsd:schema>
|
||||
+1676
File diff suppressed because it is too large.
Load diff
+28
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/characteristics"
|
||||
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/characteristics"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:complexType name="CT_AdditionalCharacteristics">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="characteristic" type="CT_Characteristic" minOccurs="0"
|
||||
maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_Characteristic">
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="relation" type="ST_Relation" use="required"/>
|
||||
<xsd:attribute name="val" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="vocabulary" type="xsd:anyURI" use="optional"/>
|
||||
</xsd:complexType>
|
||||
<xsd:simpleType name="ST_Relation">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="ge"/>
|
||||
<xsd:enumeration value="le"/>
|
||||
<xsd:enumeration value="gt"/>
|
||||
<xsd:enumeration value="lt"/>
|
||||
<xsd:enumeration value="eq"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:element name="additionalCharacteristics" type="CT_AdditionalCharacteristics"/>
|
||||
</xsd:schema>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
|
||||
xmlns:s="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
|
||||
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:import namespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
|
||||
schemaLocation="shared-commonSimpleTypes.xsd"/>
|
||||
<xsd:simpleType name="ST_SourceType">
|
||||
<xsd:restriction base="s:ST_String">
|
||||
<xsd:enumeration value="ArticleInAPeriodical"/>
|
||||
<xsd:enumeration value="Book"/>
|
||||
<xsd:enumeration value="BookSection"/>
|
||||
<xsd:enumeration value="JournalArticle"/>
|
||||
<xsd:enumeration value="ConferenceProceedings"/>
|
||||
<xsd:enumeration value="Report"/>
|
||||
<xsd:enumeration value="SoundRecording"/>
|
||||
<xsd:enumeration value="Performance"/>
|
||||
<xsd:enumeration value="Art"/>
|
||||
<xsd:enumeration value="DocumentFromInternetSite"/>
|
||||
<xsd:enumeration value="InternetSite"/>
|
||||
<xsd:enumeration value="Film"/>
|
||||
<xsd:enumeration value="Interview"/>
|
||||
<xsd:enumeration value="Patent"/>
|
||||
<xsd:enumeration value="ElectronicSource"/>
|
||||
<xsd:enumeration value="Case"/>
|
||||
<xsd:enumeration value="Misc"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:complexType name="CT_NameListType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="Person" type="CT_PersonType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_PersonType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="Last" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element name="First" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element name="Middle" type="s:ST_String" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_NameType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="NameList" type="CT_NameListType" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_NameOrCorporateType">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="NameList" type="CT_NameListType" minOccurs="1" maxOccurs="1"/>
|
||||
<xsd:element name="Corporate" minOccurs="1" maxOccurs="1" type="s:ST_String"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_AuthorType">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="Artist" type="CT_NameType"/>
|
||||
<xsd:element name="Author" type="CT_NameOrCorporateType"/>
|
||||
<xsd:element name="BookAuthor" type="CT_NameType"/>
|
||||
<xsd:element name="Compiler" type="CT_NameType"/>
|
||||
<xsd:element name="Composer" type="CT_NameType"/>
|
||||
<xsd:element name="Conductor" type="CT_NameType"/>
|
||||
<xsd:element name="Counsel" type="CT_NameType"/>
|
||||
<xsd:element name="Director" type="CT_NameType"/>
|
||||
<xsd:element name="Editor" type="CT_NameType"/>
|
||||
<xsd:element name="Interviewee" type="CT_NameType"/>
|
||||
<xsd:element name="Interviewer" type="CT_NameType"/>
|
||||
<xsd:element name="Inventor" type="CT_NameType"/>
|
||||
<xsd:element name="Performer" type="CT_NameOrCorporateType"/>
|
||||
<xsd:element name="ProducerName" type="CT_NameType"/>
|
||||
<xsd:element name="Translator" type="CT_NameType"/>
|
||||
<xsd:element name="Writer" type="CT_NameType"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="CT_SourceType">
|
||||
<xsd:sequence>
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="AbbreviatedCaseNumber" type="s:ST_String"/>
|
||||
<xsd:element name="AlbumTitle" type="s:ST_String"/>
|
||||
<xsd:element name="Author" type="CT_AuthorType"/>
|
||||
<xsd:element name="BookTitle" type="s:ST_String"/>
|
||||
<xsd:element name="Broadcaster" type="s:ST_String"/>
|
||||
<xsd:element name="BroadcastTitle" type="s:ST_String"/>
|
||||
<xsd:element name="CaseNumber" type="s:ST_String"/>
|
||||
<xsd:element name="ChapterNumber" type="s:ST_String"/>
|
||||
<xsd:element name="City" type="s:ST_String"/>
|
||||
<xsd:element name="Comments" type="s:ST_String"/>
|
||||
<xsd:element name="ConferenceName" type="s:ST_String"/>
|
||||
<xsd:element name="CountryRegion" type="s:ST_String"/>
|
||||
<xsd:element name="Court" type="s:ST_String"/>
|
||||
<xsd:element name="Day" type="s:ST_String"/>
|
||||
<xsd:element name="DayAccessed" type="s:ST_String"/>
|
||||
<xsd:element name="Department" type="s:ST_String"/>
|
||||
<xsd:element name="Distributor" type="s:ST_String"/>
|
||||
<xsd:element name="Edition" type="s:ST_String"/>
|
||||
<xsd:element name="Guid" type="s:ST_String"/>
|
||||
<xsd:element name="Institution" type="s:ST_String"/>
|
||||
<xsd:element name="InternetSiteTitle" type="s:ST_String"/>
|
||||
<xsd:element name="Issue" type="s:ST_String"/>
|
||||
<xsd:element name="JournalName" type="s:ST_String"/>
|
||||
<xsd:element name="LCID" type="s:ST_Lang"/>
|
||||
<xsd:element name="Medium" type="s:ST_String"/>
|
||||
<xsd:element name="Month" type="s:ST_String"/>
|
||||
<xsd:element name="MonthAccessed" type="s:ST_String"/>
|
||||
<xsd:element name="NumberVolumes" type="s:ST_String"/>
|
||||
<xsd:element name="Pages" type="s:ST_String"/>
|
||||
<xsd:element name="PatentNumber" type="s:ST_String"/>
|
||||
<xsd:element name="PeriodicalTitle" type="s:ST_String"/>
|
||||
<xsd:element name="ProductionCompany" type="s:ST_String"/>
|
||||
<xsd:element name="PublicationTitle" type="s:ST_String"/>
|
||||
<xsd:element name="Publisher" type="s:ST_String"/>
|
||||
<xsd:element name="RecordingNumber" type="s:ST_String"/>
|
||||
<xsd:element name="RefOrder" type="s:ST_String"/>
|
||||
<xsd:element name="Reporter" type="s:ST_String"/>
|
||||
<xsd:element name="SourceType" type="ST_SourceType"/>
|
||||
<xsd:element name="ShortTitle" type="s:ST_String"/>
|
||||
<xsd:element name="StandardNumber" type="s:ST_String"/>
|
||||
<xsd:element name="StateProvince" type="s:ST_String"/>
|
||||
<xsd:element name="Station" type="s:ST_String"/>
|
||||
<xsd:element name="Tag" type="s:ST_String"/>
|
||||
<xsd:element name="Theater" type="s:ST_String"/>
|
||||
<xsd:element name="ThesisType" type="s:ST_String"/>
|
||||
<xsd:element name="Title" type="s:ST_String"/>
|
||||
<xsd:element name="Type" type="s:ST_String"/>
|
||||
<xsd:element name="URL" type="s:ST_String"/>
|
||||
<xsd:element name="Version" type="s:ST_String"/>
|
||||
<xsd:element name="Volume" type="s:ST_String"/>
|
||||
<xsd:element name="Year" type="s:ST_String"/>
|
||||
<xsd:element name="YearAccessed" type="s:ST_String"/>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:element name="Sources" type="CT_Sources"/>
|
||||
<xsd:complexType name="CT_Sources">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="Source" type="CT_SourceType" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="SelectedStyle" type="s:ST_String"/>
|
||||
<xsd:attribute name="StyleName" type="s:ST_String"/>
|
||||
<xsd:attribute name="URI" type="s:ST_String"/>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
|
||||
targetNamespace="http://schemas.openxmlformats.org/officeDocument/2006/sharedTypes"
|
||||
elementFormDefault="qualified">
|
||||
<xsd:simpleType name="ST_Lang">
|
||||
<xsd:restriction base="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_HexColorRGB">
|
||||
<xsd:restriction base="xsd:hexBinary">
|
||||
<xsd:length value="3" fixed="true"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_Panose">
|
||||
<xsd:restriction base="xsd:hexBinary">
|
||||
<xsd:length value="10"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_CalendarType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="gregorian"/>
|
||||
<xsd:enumeration value="gregorianUs"/>
|
||||
<xsd:enumeration value="gregorianMeFrench"/>
|
||||
<xsd:enumeration value="gregorianArabic"/>
|
||||
<xsd:enumeration value="hijri"/>
|
||||
<xsd:enumeration value="hebrew"/>
|
||||
<xsd:enumeration value="taiwan"/>
|
||||
<xsd:enumeration value="japan"/>
|
||||
<xsd:enumeration value="thai"/>
|
||||
<xsd:enumeration value="korea"/>
|
||||
<xsd:enumeration value="saka"/>
|
||||
<xsd:enumeration value="gregorianXlitEnglish"/>
|
||||
<xsd:enumeration value="gregorianXlitFrench"/>
|
||||
<xsd:enumeration value="none"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_AlgClass">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="hash"/>
|
||||
<xsd:enumeration value="custom"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_CryptProv">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="rsaAES"/>
|
||||
<xsd:enumeration value="rsaFull"/>
|
||||
<xsd:enumeration value="custom"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_AlgType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="typeAny"/>
|
||||
<xsd:enumeration value="custom"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_ColorType">
|
||||
<xsd:restriction base="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_Guid">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:pattern value="\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_OnOff">
|
||||
<xsd:union memberTypes="xsd:boolean ST_OnOff1"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_OnOff1">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="on"/>
|
||||
<xsd:enumeration value="off"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_String">
|
||||
<xsd:restriction base="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_XmlName">
|
||||
<xsd:restriction base="xsd:NCName">
|
||||
<xsd:minLength value="1"/>
|
||||
<xsd:maxLength value="255"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_TrueFalse">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="t"/>
|
||||
<xsd:enumeration value="f"/>
|
||||
<xsd:enumeration value="true"/>
|
||||
<xsd:enumeration value="false"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_TrueFalseBlank">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="t"/>
|
||||
<xsd:enumeration value="f"/>
|
||||
<xsd:enumeration value="true"/>
|
||||
<xsd:enumeration value="false"/>
|
||||
<xsd:enumeration value=""/>
|
||||
<xsd:enumeration value="True"/>
|
||||
<xsd:enumeration value="False"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_UnsignedDecimalNumber">
|
||||
<xsd:restriction base="xsd:decimal">
|
||||
<xsd:minInclusive value="0"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_TwipsMeasure">
|
||||
<xsd:union memberTypes="ST_UnsignedDecimalNumber ST_PositiveUniversalMeasure"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_VerticalAlignRun">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="baseline"/>
|
||||
<xsd:enumeration value="superscript"/>
|
||||
<xsd:enumeration value="subscript"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_Xstring">
|
||||
<xsd:restriction base="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_XAlign">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="left"/>
|
||||
<xsd:enumeration value="center"/>
|
||||
<xsd:enumeration value="right"/>
|
||||
<xsd:enumeration value="inside"/>
|
||||
<xsd:enumeration value="outside"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_YAlign">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="inline"/>
|
||||
<xsd:enumeration value="top"/>
|
||||
<xsd:enumeration value="center"/>
|
||||
<xsd:enumeration value="bottom"/>
|
||||
<xsd:enumeration value="inside"/>
|
||||
<xsd:enumeration value="outside"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_ConformanceClass">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="strict"/>
|
||||
<xsd:enumeration value="transitional"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_UniversalMeasure">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_PositiveUniversalMeasure">
|
||||
<xsd:restriction base="ST_UniversalMeasure">
|
||||
<xsd:pattern value="[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_Percentage">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?%"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_FixedPercentage">
|
||||
<xsd:restriction base="ST_Percentage">
|
||||
<xsd:pattern value="-?((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_PositivePercentage">
|
||||
<xsd:restriction base="ST_Percentage">
|
||||
<xsd:pattern value="[0-9]+(\.[0-9]+)?%"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
<xsd:simpleType name="ST_PositiveFixedPercentage">
|
||||
<xsd:restriction base="ST_Percentage">
|
||||
<xsd:pattern value="((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%"/>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:schema>
|
||||
Loaded 100 of 398 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user