@papert-code/papert-code 0.3.94 → 0.3.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/chunks/{chunk-OIA427PZ.js → chunk-HSYOWGEB.js} +1 -1
- package/dist/chunks/{chunk-6ZOXSA5F.js → chunk-IK4ISYCE.js} +4 -4
- package/dist/chunks/{chunk-JATIVKZP.js → chunk-KBPFDUTA.js} +55 -10
- package/dist/chunks/{chunk-7T4OCWHU.js → chunk-TNDQXJLA.js} +1931 -787
- package/dist/chunks/{gemini-WYRXV2QC.js → gemini-MVJNXCFF.js} +20547 -16879
- package/dist/chunks/{openaiContentGenerator-EAVO6L3Y.js → openaiContentGenerator-GTG5MK5E.js} +2 -2
- package/dist/chunks/{papertContentGenerator-G4SBF3DR.js → papertContentGenerator-Q5TTXUE6.js} +3 -3
- package/dist/chunks/{server-N2U4FF55.js → server-6D3KYATG.js} +7 -1
- package/dist/cli.js +5 -4
- package/dist/sandbox-macos-permissive-proxied.sb +1 -1
- package/dist/sandbox-macos-restrictive-proxied.sb +1 -1
- package/dist/skills/algorithmic-art/SKILL.md +405 -0
- package/dist/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/dist/skills/algorithmic-art/templates/viewer.html +599 -0
- package/dist/skills/brand-guidelines/SKILL.md +73 -0
- package/dist/skills/canvas-design/SKILL.md +130 -0
- package/dist/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/dist/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/dist/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/dist/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/dist/skills/doc-coauthoring/SKILL.md +375 -0
- package/dist/skills/docx/SKILL.md +481 -0
- package/dist/skills/docx/scripts/__init__.py +1 -0
- package/dist/skills/docx/scripts/accept_changes.py +135 -0
- package/dist/skills/docx/scripts/comment.py +318 -0
- package/dist/skills/docx/scripts/office/helpers/__init__.py +0 -0
- package/dist/skills/docx/scripts/office/helpers/merge_runs.py +199 -0
- package/dist/skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/dist/skills/docx/scripts/office/pack.py +159 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/dist/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/dist/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/dist/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/dist/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/dist/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/dist/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/dist/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/dist/skills/docx/scripts/office/soffice.py +183 -0
- package/dist/skills/docx/scripts/office/unpack.py +132 -0
- package/dist/skills/docx/scripts/office/validate.py +111 -0
- package/dist/skills/docx/scripts/office/validators/__init__.py +15 -0
- package/dist/skills/docx/scripts/office/validators/base.py +847 -0
- package/dist/skills/docx/scripts/office/validators/docx.py +446 -0
- package/dist/skills/docx/scripts/office/validators/pptx.py +275 -0
- package/dist/skills/docx/scripts/office/validators/redlining.py +247 -0
- package/dist/skills/docx/scripts/templates/comments.xml +3 -0
- package/dist/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/dist/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/dist/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/dist/skills/docx/scripts/templates/people.xml +3 -0
- package/dist/skills/frontend-design/SKILL.md +42 -0
- package/dist/skills/internal-comms/SKILL.md +32 -0
- package/dist/skills/internal-comms/examples/3p-updates.md +47 -0
- package/dist/skills/internal-comms/examples/company-newsletter.md +65 -0
- package/dist/skills/internal-comms/examples/faq-answers.md +30 -0
- package/dist/skills/internal-comms/examples/general-comms.md +16 -0
- package/dist/skills/mcp-builder/SKILL.md +236 -0
- package/dist/skills/mcp-builder/reference/evaluation.md +602 -0
- package/dist/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/dist/skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/dist/skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/dist/skills/mcp-builder/scripts/connections.py +151 -0
- package/dist/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/dist/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/dist/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/dist/skills/papert-code/SKILL.md +561 -0
- package/dist/skills/pdf/SKILL.md +314 -0
- package/dist/skills/pdf/forms.md +294 -0
- package/dist/skills/pdf/reference.md +612 -0
- package/dist/skills/pdf/scripts/check_bounding_boxes.py +65 -0
- package/dist/skills/pdf/scripts/check_fillable_fields.py +11 -0
- package/dist/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
- package/dist/skills/pdf/scripts/create_validation_image.py +37 -0
- package/dist/skills/pdf/scripts/extract_form_field_info.py +122 -0
- package/dist/skills/pdf/scripts/extract_form_structure.py +115 -0
- package/dist/skills/pdf/scripts/fill_fillable_fields.py +98 -0
- package/dist/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/dist/skills/pptx/SKILL.md +232 -0
- package/dist/skills/pptx/editing.md +205 -0
- package/dist/skills/pptx/pptxgenjs.md +420 -0
- package/dist/skills/pptx/scripts/__init__.py +0 -0
- package/dist/skills/pptx/scripts/add_slide.py +195 -0
- package/dist/skills/pptx/scripts/clean.py +286 -0
- package/dist/skills/pptx/scripts/office/helpers/__init__.py +0 -0
- package/dist/skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
- package/dist/skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/dist/skills/pptx/scripts/office/pack.py +159 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/dist/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/dist/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/dist/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/dist/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/dist/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/dist/skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/dist/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/dist/skills/pptx/scripts/office/soffice.py +183 -0
- package/dist/skills/pptx/scripts/office/unpack.py +132 -0
- package/dist/skills/pptx/scripts/office/validate.py +111 -0
- package/dist/skills/pptx/scripts/office/validators/__init__.py +15 -0
- package/dist/skills/pptx/scripts/office/validators/base.py +847 -0
- package/dist/skills/pptx/scripts/office/validators/docx.py +446 -0
- package/dist/skills/pptx/scripts/office/validators/pptx.py +275 -0
- package/dist/skills/pptx/scripts/office/validators/redlining.py +247 -0
- package/dist/skills/pptx/scripts/thumbnail.py +289 -0
- package/dist/skills/skill-creator/SKILL.md +357 -0
- package/dist/skills/skill-creator/references/output-patterns.md +82 -0
- package/dist/skills/skill-creator/references/workflows.md +28 -0
- package/dist/skills/skill-creator/scripts/init_skill.py +303 -0
- package/dist/skills/skill-creator/scripts/package_skill.py +110 -0
- package/dist/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/dist/skills/slack-gif-creator/SKILL.md +254 -0
- package/dist/skills/slack-gif-creator/core/easing.py +234 -0
- package/dist/skills/slack-gif-creator/core/frame_composer.py +176 -0
- package/dist/skills/slack-gif-creator/core/gif_builder.py +269 -0
- package/dist/skills/slack-gif-creator/core/validators.py +136 -0
- package/dist/skills/slack-gif-creator/requirements.txt +4 -0
- package/dist/skills/theme-factory/SKILL.md +59 -0
- package/dist/skills/theme-factory/theme-showcase.pdf +0 -0
- package/dist/skills/theme-factory/themes/arctic-frost.md +19 -0
- package/dist/skills/theme-factory/themes/botanical-garden.md +19 -0
- package/dist/skills/theme-factory/themes/desert-rose.md +19 -0
- package/dist/skills/theme-factory/themes/forest-canopy.md +19 -0
- package/dist/skills/theme-factory/themes/golden-hour.md +19 -0
- package/dist/skills/theme-factory/themes/midnight-galaxy.md +19 -0
- package/dist/skills/theme-factory/themes/modern-minimalist.md +19 -0
- package/dist/skills/theme-factory/themes/ocean-depths.md +19 -0
- package/dist/skills/theme-factory/themes/sunset-boulevard.md +19 -0
- package/dist/skills/theme-factory/themes/tech-innovation.md +19 -0
- package/dist/skills/web-artifacts-builder/SKILL.md +74 -0
- package/dist/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/dist/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/dist/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/dist/skills/webapp-testing/SKILL.md +96 -0
- package/dist/skills/webapp-testing/examples/console_logging.py +35 -0
- package/dist/skills/webapp-testing/examples/element_discovery.py +40 -0
- package/dist/skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/dist/skills/webapp-testing/scripts/with_server.py +106 -0
- package/dist/skills/xlsx/SKILL.md +292 -0
- package/dist/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
- package/dist/skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
- package/dist/skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
- package/dist/skills/xlsx/scripts/office/pack.py +159 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/dist/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/dist/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/dist/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/dist/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/dist/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/dist/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/dist/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/dist/skills/xlsx/scripts/office/soffice.py +183 -0
- package/dist/skills/xlsx/scripts/office/unpack.py +132 -0
- package/dist/skills/xlsx/scripts/office/validate.py +111 -0
- package/dist/skills/xlsx/scripts/office/validators/__init__.py +15 -0
- package/dist/skills/xlsx/scripts/office/validators/base.py +847 -0
- package/dist/skills/xlsx/scripts/office/validators/docx.py +446 -0
- package/dist/skills/xlsx/scripts/office/validators/pptx.py +275 -0
- package/dist/skills/xlsx/scripts/office/validators/redlining.py +247 -0
- package/dist/skills/xlsx/scripts/recalc.py +184 -0
- package/package.json +11 -4
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
GIF Builder - Core module for assembling frames into GIFs optimized for Slack.
|
|
4
|
+
|
|
5
|
+
This module provides the main interface for creating GIFs from programmatically
|
|
6
|
+
generated frames, with automatic optimization for Slack's requirements.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
import imageio.v3 as imageio
|
|
13
|
+
import numpy as np
|
|
14
|
+
from PIL import Image
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GIFBuilder:
|
|
18
|
+
"""Builder for creating optimized GIFs from frames."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, width: int = 480, height: int = 480, fps: int = 15):
|
|
21
|
+
"""
|
|
22
|
+
Initialize GIF builder.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
width: Frame width in pixels
|
|
26
|
+
height: Frame height in pixels
|
|
27
|
+
fps: Frames per second
|
|
28
|
+
"""
|
|
29
|
+
self.width = width
|
|
30
|
+
self.height = height
|
|
31
|
+
self.fps = fps
|
|
32
|
+
self.frames: list[np.ndarray] = []
|
|
33
|
+
|
|
34
|
+
def add_frame(self, frame: np.ndarray | Image.Image):
|
|
35
|
+
"""
|
|
36
|
+
Add a frame to the GIF.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
frame: Frame as numpy array or PIL Image (will be converted to RGB)
|
|
40
|
+
"""
|
|
41
|
+
if isinstance(frame, Image.Image):
|
|
42
|
+
frame = np.array(frame.convert("RGB"))
|
|
43
|
+
|
|
44
|
+
# Ensure frame is correct size
|
|
45
|
+
if frame.shape[:2] != (self.height, self.width):
|
|
46
|
+
pil_frame = Image.fromarray(frame)
|
|
47
|
+
pil_frame = pil_frame.resize(
|
|
48
|
+
(self.width, self.height), Image.Resampling.LANCZOS
|
|
49
|
+
)
|
|
50
|
+
frame = np.array(pil_frame)
|
|
51
|
+
|
|
52
|
+
self.frames.append(frame)
|
|
53
|
+
|
|
54
|
+
def add_frames(self, frames: list[np.ndarray | Image.Image]):
|
|
55
|
+
"""Add multiple frames at once."""
|
|
56
|
+
for frame in frames:
|
|
57
|
+
self.add_frame(frame)
|
|
58
|
+
|
|
59
|
+
def optimize_colors(
|
|
60
|
+
self, num_colors: int = 128, use_global_palette: bool = True
|
|
61
|
+
) -> list[np.ndarray]:
|
|
62
|
+
"""
|
|
63
|
+
Reduce colors in all frames using quantization.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
num_colors: Target number of colors (8-256)
|
|
67
|
+
use_global_palette: Use a single palette for all frames (better compression)
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
List of color-optimized frames
|
|
71
|
+
"""
|
|
72
|
+
optimized = []
|
|
73
|
+
|
|
74
|
+
if use_global_palette and len(self.frames) > 1:
|
|
75
|
+
# Create a global palette from all frames
|
|
76
|
+
# Sample frames to build palette
|
|
77
|
+
sample_size = min(5, len(self.frames))
|
|
78
|
+
sample_indices = [
|
|
79
|
+
int(i * len(self.frames) / sample_size) for i in range(sample_size)
|
|
80
|
+
]
|
|
81
|
+
sample_frames = [self.frames[i] for i in sample_indices]
|
|
82
|
+
|
|
83
|
+
# Combine sample frames into a single image for palette generation
|
|
84
|
+
# Flatten each frame to get all pixels, then stack them
|
|
85
|
+
all_pixels = np.vstack(
|
|
86
|
+
[f.reshape(-1, 3) for f in sample_frames]
|
|
87
|
+
) # (total_pixels, 3)
|
|
88
|
+
|
|
89
|
+
# Create a properly-shaped RGB image from the pixel data
|
|
90
|
+
# We'll make a roughly square image from all the pixels
|
|
91
|
+
total_pixels = len(all_pixels)
|
|
92
|
+
width = min(512, int(np.sqrt(total_pixels))) # Reasonable width, max 512
|
|
93
|
+
height = (total_pixels + width - 1) // width # Ceiling division
|
|
94
|
+
|
|
95
|
+
# Pad if necessary to fill the rectangle
|
|
96
|
+
pixels_needed = width * height
|
|
97
|
+
if pixels_needed > total_pixels:
|
|
98
|
+
padding = np.zeros((pixels_needed - total_pixels, 3), dtype=np.uint8)
|
|
99
|
+
all_pixels = np.vstack([all_pixels, padding])
|
|
100
|
+
|
|
101
|
+
# Reshape to proper RGB image format (H, W, 3)
|
|
102
|
+
img_array = (
|
|
103
|
+
all_pixels[:pixels_needed].reshape(height, width, 3).astype(np.uint8)
|
|
104
|
+
)
|
|
105
|
+
combined_img = Image.fromarray(img_array, mode="RGB")
|
|
106
|
+
|
|
107
|
+
# Generate global palette
|
|
108
|
+
global_palette = combined_img.quantize(colors=num_colors, method=2)
|
|
109
|
+
|
|
110
|
+
# Apply global palette to all frames
|
|
111
|
+
for frame in self.frames:
|
|
112
|
+
pil_frame = Image.fromarray(frame)
|
|
113
|
+
quantized = pil_frame.quantize(palette=global_palette, dither=1)
|
|
114
|
+
optimized.append(np.array(quantized.convert("RGB")))
|
|
115
|
+
else:
|
|
116
|
+
# Use per-frame quantization
|
|
117
|
+
for frame in self.frames:
|
|
118
|
+
pil_frame = Image.fromarray(frame)
|
|
119
|
+
quantized = pil_frame.quantize(colors=num_colors, method=2, dither=1)
|
|
120
|
+
optimized.append(np.array(quantized.convert("RGB")))
|
|
121
|
+
|
|
122
|
+
return optimized
|
|
123
|
+
|
|
124
|
+
def deduplicate_frames(self, threshold: float = 0.9995) -> int:
|
|
125
|
+
"""
|
|
126
|
+
Remove duplicate or near-duplicate consecutive frames.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
threshold: Similarity threshold (0.0-1.0). Higher = more strict (0.9995 = nearly identical).
|
|
130
|
+
Use 0.9995+ to preserve subtle animations, 0.98 for aggressive removal.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Number of frames removed
|
|
134
|
+
"""
|
|
135
|
+
if len(self.frames) < 2:
|
|
136
|
+
return 0
|
|
137
|
+
|
|
138
|
+
deduplicated = [self.frames[0]]
|
|
139
|
+
removed_count = 0
|
|
140
|
+
|
|
141
|
+
for i in range(1, len(self.frames)):
|
|
142
|
+
# Compare with previous frame
|
|
143
|
+
prev_frame = np.array(deduplicated[-1], dtype=np.float32)
|
|
144
|
+
curr_frame = np.array(self.frames[i], dtype=np.float32)
|
|
145
|
+
|
|
146
|
+
# Calculate similarity (normalized)
|
|
147
|
+
diff = np.abs(prev_frame - curr_frame)
|
|
148
|
+
similarity = 1.0 - (np.mean(diff) / 255.0)
|
|
149
|
+
|
|
150
|
+
# Keep frame if sufficiently different
|
|
151
|
+
# High threshold (0.9995+) means only remove nearly identical frames
|
|
152
|
+
if similarity < threshold:
|
|
153
|
+
deduplicated.append(self.frames[i])
|
|
154
|
+
else:
|
|
155
|
+
removed_count += 1
|
|
156
|
+
|
|
157
|
+
self.frames = deduplicated
|
|
158
|
+
return removed_count
|
|
159
|
+
|
|
160
|
+
def save(
|
|
161
|
+
self,
|
|
162
|
+
output_path: str | Path,
|
|
163
|
+
num_colors: int = 128,
|
|
164
|
+
optimize_for_emoji: bool = False,
|
|
165
|
+
remove_duplicates: bool = False,
|
|
166
|
+
) -> dict:
|
|
167
|
+
"""
|
|
168
|
+
Save frames as optimized GIF for Slack.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
output_path: Where to save the GIF
|
|
172
|
+
num_colors: Number of colors to use (fewer = smaller file)
|
|
173
|
+
optimize_for_emoji: If True, optimize for emoji size (128x128, fewer colors)
|
|
174
|
+
remove_duplicates: If True, remove duplicate consecutive frames (opt-in)
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Dictionary with file info (path, size, dimensions, frame_count)
|
|
178
|
+
"""
|
|
179
|
+
if not self.frames:
|
|
180
|
+
raise ValueError("No frames to save. Add frames with add_frame() first.")
|
|
181
|
+
|
|
182
|
+
output_path = Path(output_path)
|
|
183
|
+
|
|
184
|
+
# Remove duplicate frames to reduce file size
|
|
185
|
+
if remove_duplicates:
|
|
186
|
+
removed = self.deduplicate_frames(threshold=0.9995)
|
|
187
|
+
if removed > 0:
|
|
188
|
+
print(
|
|
189
|
+
f" Removed {removed} nearly identical frames (preserved subtle animations)"
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Optimize for emoji if requested
|
|
193
|
+
if optimize_for_emoji:
|
|
194
|
+
if self.width > 128 or self.height > 128:
|
|
195
|
+
print(
|
|
196
|
+
f" Resizing from {self.width}x{self.height} to 128x128 for emoji"
|
|
197
|
+
)
|
|
198
|
+
self.width = 128
|
|
199
|
+
self.height = 128
|
|
200
|
+
# Resize all frames
|
|
201
|
+
resized_frames = []
|
|
202
|
+
for frame in self.frames:
|
|
203
|
+
pil_frame = Image.fromarray(frame)
|
|
204
|
+
pil_frame = pil_frame.resize((128, 128), Image.Resampling.LANCZOS)
|
|
205
|
+
resized_frames.append(np.array(pil_frame))
|
|
206
|
+
self.frames = resized_frames
|
|
207
|
+
num_colors = min(num_colors, 48) # More aggressive color limit for emoji
|
|
208
|
+
|
|
209
|
+
# More aggressive FPS reduction for emoji
|
|
210
|
+
if len(self.frames) > 12:
|
|
211
|
+
print(
|
|
212
|
+
f" Reducing frames from {len(self.frames)} to ~12 for emoji size"
|
|
213
|
+
)
|
|
214
|
+
# Keep every nth frame to get close to 12 frames
|
|
215
|
+
keep_every = max(1, len(self.frames) // 12)
|
|
216
|
+
self.frames = [
|
|
217
|
+
self.frames[i] for i in range(0, len(self.frames), keep_every)
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
# Optimize colors with global palette
|
|
221
|
+
optimized_frames = self.optimize_colors(num_colors, use_global_palette=True)
|
|
222
|
+
|
|
223
|
+
# Calculate frame duration in milliseconds
|
|
224
|
+
frame_duration = 1000 / self.fps
|
|
225
|
+
|
|
226
|
+
# Save GIF
|
|
227
|
+
imageio.imwrite(
|
|
228
|
+
output_path,
|
|
229
|
+
optimized_frames,
|
|
230
|
+
duration=frame_duration,
|
|
231
|
+
loop=0, # Infinite loop
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Get file info
|
|
235
|
+
file_size_kb = output_path.stat().st_size / 1024
|
|
236
|
+
file_size_mb = file_size_kb / 1024
|
|
237
|
+
|
|
238
|
+
info = {
|
|
239
|
+
"path": str(output_path),
|
|
240
|
+
"size_kb": file_size_kb,
|
|
241
|
+
"size_mb": file_size_mb,
|
|
242
|
+
"dimensions": f"{self.width}x{self.height}",
|
|
243
|
+
"frame_count": len(optimized_frames),
|
|
244
|
+
"fps": self.fps,
|
|
245
|
+
"duration_seconds": len(optimized_frames) / self.fps,
|
|
246
|
+
"colors": num_colors,
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Print info
|
|
250
|
+
print(f"\n✓ GIF created successfully!")
|
|
251
|
+
print(f" Path: {output_path}")
|
|
252
|
+
print(f" Size: {file_size_kb:.1f} KB ({file_size_mb:.2f} MB)")
|
|
253
|
+
print(f" Dimensions: {self.width}x{self.height}")
|
|
254
|
+
print(f" Frames: {len(optimized_frames)} @ {self.fps} fps")
|
|
255
|
+
print(f" Duration: {info['duration_seconds']:.1f}s")
|
|
256
|
+
print(f" Colors: {num_colors}")
|
|
257
|
+
|
|
258
|
+
# Size info
|
|
259
|
+
if optimize_for_emoji:
|
|
260
|
+
print(f" Optimized for emoji (128x128, reduced colors)")
|
|
261
|
+
if file_size_mb > 1.0:
|
|
262
|
+
print(f"\n Note: Large file size ({file_size_kb:.1f} KB)")
|
|
263
|
+
print(" Consider: fewer frames, smaller dimensions, or fewer colors")
|
|
264
|
+
|
|
265
|
+
return info
|
|
266
|
+
|
|
267
|
+
def clear(self):
|
|
268
|
+
"""Clear all frames (useful for creating multiple GIFs)."""
|
|
269
|
+
self.frames = []
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Validators - Check if GIFs meet Slack's requirements.
|
|
4
|
+
|
|
5
|
+
These validators help ensure your GIFs meet Slack's size and dimension constraints.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def validate_gif(
|
|
12
|
+
gif_path: str | Path, is_emoji: bool = True, verbose: bool = True
|
|
13
|
+
) -> tuple[bool, dict]:
|
|
14
|
+
"""
|
|
15
|
+
Validate GIF for Slack (dimensions, size, frame count).
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
gif_path: Path to GIF file
|
|
19
|
+
is_emoji: True for emoji (128x128 recommended), False for message GIF
|
|
20
|
+
verbose: Print validation details
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Tuple of (passes: bool, results: dict with all details)
|
|
24
|
+
"""
|
|
25
|
+
from PIL import Image
|
|
26
|
+
|
|
27
|
+
gif_path = Path(gif_path)
|
|
28
|
+
|
|
29
|
+
if not gif_path.exists():
|
|
30
|
+
return False, {"error": f"File not found: {gif_path}"}
|
|
31
|
+
|
|
32
|
+
# Get file size
|
|
33
|
+
size_bytes = gif_path.stat().st_size
|
|
34
|
+
size_kb = size_bytes / 1024
|
|
35
|
+
size_mb = size_kb / 1024
|
|
36
|
+
|
|
37
|
+
# Get dimensions and frame info
|
|
38
|
+
try:
|
|
39
|
+
with Image.open(gif_path) as img:
|
|
40
|
+
width, height = img.size
|
|
41
|
+
|
|
42
|
+
# Count frames
|
|
43
|
+
frame_count = 0
|
|
44
|
+
try:
|
|
45
|
+
while True:
|
|
46
|
+
img.seek(frame_count)
|
|
47
|
+
frame_count += 1
|
|
48
|
+
except EOFError:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
# Get duration
|
|
52
|
+
try:
|
|
53
|
+
duration_ms = img.info.get("duration", 100)
|
|
54
|
+
total_duration = (duration_ms * frame_count) / 1000
|
|
55
|
+
fps = frame_count / total_duration if total_duration > 0 else 0
|
|
56
|
+
except:
|
|
57
|
+
total_duration = None
|
|
58
|
+
fps = None
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
return False, {"error": f"Failed to read GIF: {e}"}
|
|
62
|
+
|
|
63
|
+
# Validate dimensions
|
|
64
|
+
if is_emoji:
|
|
65
|
+
optimal = width == height == 128
|
|
66
|
+
acceptable = width == height and 64 <= width <= 128
|
|
67
|
+
dim_pass = acceptable
|
|
68
|
+
else:
|
|
69
|
+
aspect_ratio = (
|
|
70
|
+
max(width, height) / min(width, height)
|
|
71
|
+
if min(width, height) > 0
|
|
72
|
+
else float("inf")
|
|
73
|
+
)
|
|
74
|
+
dim_pass = aspect_ratio <= 2.0 and 320 <= min(width, height) <= 640
|
|
75
|
+
|
|
76
|
+
results = {
|
|
77
|
+
"file": str(gif_path),
|
|
78
|
+
"passes": dim_pass,
|
|
79
|
+
"width": width,
|
|
80
|
+
"height": height,
|
|
81
|
+
"size_kb": size_kb,
|
|
82
|
+
"size_mb": size_mb,
|
|
83
|
+
"frame_count": frame_count,
|
|
84
|
+
"duration_seconds": total_duration,
|
|
85
|
+
"fps": fps,
|
|
86
|
+
"is_emoji": is_emoji,
|
|
87
|
+
"optimal": optimal if is_emoji else None,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Print if verbose
|
|
91
|
+
if verbose:
|
|
92
|
+
print(f"\nValidating {gif_path.name}:")
|
|
93
|
+
print(
|
|
94
|
+
f" Dimensions: {width}x{height}"
|
|
95
|
+
+ (
|
|
96
|
+
f" ({'optimal' if optimal else 'acceptable'})"
|
|
97
|
+
if is_emoji and acceptable
|
|
98
|
+
else ""
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
print(
|
|
102
|
+
f" Size: {size_kb:.1f} KB"
|
|
103
|
+
+ (f" ({size_mb:.2f} MB)" if size_mb >= 1.0 else "")
|
|
104
|
+
)
|
|
105
|
+
print(
|
|
106
|
+
f" Frames: {frame_count}"
|
|
107
|
+
+ (f" @ {fps:.1f} fps ({total_duration:.1f}s)" if fps else "")
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not dim_pass:
|
|
111
|
+
print(
|
|
112
|
+
f" Note: {'Emoji should be 128x128' if is_emoji else 'Unusual dimensions for Slack'}"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if size_mb > 5.0:
|
|
116
|
+
print(f" Note: Large file size - consider fewer frames/colors")
|
|
117
|
+
|
|
118
|
+
return dim_pass, results
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def is_slack_ready(
|
|
122
|
+
gif_path: str | Path, is_emoji: bool = True, verbose: bool = True
|
|
123
|
+
) -> bool:
|
|
124
|
+
"""
|
|
125
|
+
Quick check if GIF is ready for Slack.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
gif_path: Path to GIF file
|
|
129
|
+
is_emoji: True for emoji GIF, False for message GIF
|
|
130
|
+
verbose: Print feedback
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
True if dimensions are acceptable
|
|
134
|
+
"""
|
|
135
|
+
passes, _ = validate_gif(gif_path, is_emoji, verbose)
|
|
136
|
+
return passes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: theme-factory
|
|
3
|
+
description: Toolkit for styling artifacts with a theme. These artifacts can be slides, docs, reportings, HTML landing pages, etc. There are 10 pre-set themes with colors/fonts that you can apply to any artifact that has been creating, or can generate a new theme on-the-fly.
|
|
4
|
+
license: Complete terms in LICENSE.txt
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Theme Factory Skill
|
|
9
|
+
|
|
10
|
+
This skill provides a curated collection of professional font and color themes themes, each with carefully selected color palettes and font pairings. Once a theme is chosen, it can be applied to any artifact.
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
To apply consistent, professional styling to presentation slide decks, use this skill. Each theme includes:
|
|
15
|
+
- A cohesive color palette with hex codes
|
|
16
|
+
- Complementary font pairings for headers and body text
|
|
17
|
+
- A distinct visual identity suitable for different contexts and audiences
|
|
18
|
+
|
|
19
|
+
## Usage Instructions
|
|
20
|
+
|
|
21
|
+
To apply styling to a slide deck or other artifact:
|
|
22
|
+
|
|
23
|
+
1. **Show the theme showcase**: Display the `theme-showcase.pdf` file to allow users to see all available themes visually. Do not make any modifications to it; simply show the file for viewing.
|
|
24
|
+
2. **Ask for their choice**: Ask which theme to apply to the deck
|
|
25
|
+
3. **Wait for selection**: Get explicit confirmation about the chosen theme
|
|
26
|
+
4. **Apply the theme**: Once a theme has been chosen, apply the selected theme's colors and fonts to the deck/artifact
|
|
27
|
+
|
|
28
|
+
## Themes Available
|
|
29
|
+
|
|
30
|
+
The following 10 themes are available, each showcased in `theme-showcase.pdf`:
|
|
31
|
+
|
|
32
|
+
1. **Ocean Depths** - Professional and calming maritime theme
|
|
33
|
+
2. **Sunset Boulevard** - Warm and vibrant sunset colors
|
|
34
|
+
3. **Forest Canopy** - Natural and grounded earth tones
|
|
35
|
+
4. **Modern Minimalist** - Clean and contemporary grayscale
|
|
36
|
+
5. **Golden Hour** - Rich and warm autumnal palette
|
|
37
|
+
6. **Arctic Frost** - Cool and crisp winter-inspired theme
|
|
38
|
+
7. **Desert Rose** - Soft and sophisticated dusty tones
|
|
39
|
+
8. **Tech Innovation** - Bold and modern tech aesthetic
|
|
40
|
+
9. **Botanical Garden** - Fresh and organic garden colors
|
|
41
|
+
10. **Midnight Galaxy** - Dramatic and cosmic deep tones
|
|
42
|
+
|
|
43
|
+
## Theme Details
|
|
44
|
+
|
|
45
|
+
Each theme is defined in the `themes/` directory with complete specifications including:
|
|
46
|
+
- Cohesive color palette with hex codes
|
|
47
|
+
- Complementary font pairings for headers and body text
|
|
48
|
+
- Distinct visual identity suitable for different contexts and audiences
|
|
49
|
+
|
|
50
|
+
## Application Process
|
|
51
|
+
|
|
52
|
+
After a preferred theme is selected:
|
|
53
|
+
1. Read the corresponding theme file from the `themes/` directory
|
|
54
|
+
2. Apply the specified colors and fonts consistently throughout the deck
|
|
55
|
+
3. Ensure proper contrast and readability
|
|
56
|
+
4. Maintain the theme's visual identity across all slides
|
|
57
|
+
|
|
58
|
+
## Create your Own Theme
|
|
59
|
+
To handle cases where none of the existing themes work for an artifact, create a custom theme. Based on provided inputs, generate a new theme similar to the ones above. Give the theme a similar name describing what the font/color combinations represent. Use any basic description provided to choose appropriate colors/fonts. After generating the theme, show it for review and verification. Following that, apply the theme as described above.
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Arctic Frost
|
|
2
|
+
|
|
3
|
+
A cool and crisp winter-inspired theme that conveys clarity, precision, and professionalism.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Ice Blue**: `#d4e4f7` - Light backgrounds and highlights
|
|
8
|
+
- **Steel Blue**: `#4a6fa5` - Primary accent color
|
|
9
|
+
- **Silver**: `#c0c0c0` - Metallic accent elements
|
|
10
|
+
- **Crisp White**: `#fafafa` - Clean backgrounds and text
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Sans Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Healthcare presentations, technology solutions, winter sports, clean tech, pharmaceutical content.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Botanical Garden
|
|
2
|
+
|
|
3
|
+
A fresh and organic theme featuring vibrant garden-inspired colors for lively presentations.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Fern Green**: `#4a7c59` - Rich natural green
|
|
8
|
+
- **Marigold**: `#f9a620` - Bright floral accent
|
|
9
|
+
- **Terracotta**: `#b7472a` - Earthy warm tone
|
|
10
|
+
- **Cream**: `#f5f3ed` - Soft neutral backgrounds
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Serif Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Garden centers, food presentations, farm-to-table content, botanical brands, natural products.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Desert Rose
|
|
2
|
+
|
|
3
|
+
A soft and sophisticated theme with dusty, muted tones perfect for elegant presentations.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Dusty Rose**: `#d4a5a5` - Soft primary color
|
|
8
|
+
- **Clay**: `#b87d6d` - Earthy accent
|
|
9
|
+
- **Sand**: `#e8d5c4` - Warm neutral backgrounds
|
|
10
|
+
- **Deep Burgundy**: `#5d2e46` - Rich dark contrast
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: FreeSans Bold
|
|
15
|
+
- **Body Text**: FreeSans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Fashion presentations, beauty brands, wedding planning, interior design, boutique businesses.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Forest Canopy
|
|
2
|
+
|
|
3
|
+
A natural and grounded theme featuring earth tones inspired by dense forest environments.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Forest Green**: `#2d4a2b` - Primary dark green
|
|
8
|
+
- **Sage**: `#7d8471` - Muted green accent
|
|
9
|
+
- **Olive**: `#a4ac86` - Light accent color
|
|
10
|
+
- **Ivory**: `#faf9f6` - Backgrounds and text
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: FreeSerif Bold
|
|
15
|
+
- **Body Text**: FreeSans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Environmental presentations, sustainability reports, outdoor brands, wellness content, organic products.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Golden Hour
|
|
2
|
+
|
|
3
|
+
A rich and warm autumnal palette that creates an inviting and sophisticated atmosphere.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Mustard Yellow**: `#f4a900` - Bold primary accent
|
|
8
|
+
- **Terracotta**: `#c1666b` - Warm secondary color
|
|
9
|
+
- **Warm Beige**: `#d4b896` - Neutral backgrounds
|
|
10
|
+
- **Chocolate Brown**: `#4a403a` - Dark text and anchors
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: FreeSans Bold
|
|
15
|
+
- **Body Text**: FreeSans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Restaurant presentations, hospitality brands, fall campaigns, cozy lifestyle content, artisan products.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Midnight Galaxy
|
|
2
|
+
|
|
3
|
+
A dramatic and cosmic theme with deep purples and mystical tones for impactful presentations.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Deep Purple**: `#2b1e3e` - Rich dark base
|
|
8
|
+
- **Cosmic Blue**: `#4a4e8f` - Mystical mid-tone
|
|
9
|
+
- **Lavender**: `#a490c2` - Soft accent color
|
|
10
|
+
- **Silver**: `#e6e6fa` - Light highlights and text
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: FreeSans Bold
|
|
15
|
+
- **Body Text**: FreeSans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Entertainment industry, gaming presentations, nightlife venues, luxury brands, creative agencies.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Modern Minimalist
|
|
2
|
+
|
|
3
|
+
A clean and contemporary theme with a sophisticated grayscale palette for maximum versatility.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Charcoal**: `#36454f` - Primary dark color
|
|
8
|
+
- **Slate Gray**: `#708090` - Medium gray for accents
|
|
9
|
+
- **Light Gray**: `#d3d3d3` - Backgrounds and dividers
|
|
10
|
+
- **White**: `#ffffff` - Text and clean backgrounds
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Sans Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Tech presentations, architecture portfolios, design showcases, modern business proposals, data visualization.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Ocean Depths
|
|
2
|
+
|
|
3
|
+
A professional and calming maritime theme that evokes the serenity of deep ocean waters.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Deep Navy**: `#1a2332` - Primary background color
|
|
8
|
+
- **Teal**: `#2d8b8b` - Accent color for highlights and emphasis
|
|
9
|
+
- **Seafoam**: `#a8dadc` - Secondary accent for lighter elements
|
|
10
|
+
- **Cream**: `#f1faee` - Text and light backgrounds
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Sans Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Corporate presentations, financial reports, professional consulting decks, trust-building content.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Sunset Boulevard
|
|
2
|
+
|
|
3
|
+
A warm and vibrant theme inspired by golden hour sunsets, perfect for energetic and creative presentations.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Burnt Orange**: `#e76f51` - Primary accent color
|
|
8
|
+
- **Coral**: `#f4a261` - Secondary warm accent
|
|
9
|
+
- **Warm Sand**: `#e9c46a` - Highlighting and backgrounds
|
|
10
|
+
- **Deep Purple**: `#264653` - Dark contrast and text
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Serif Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Creative pitches, marketing presentations, lifestyle brands, event promotions, inspirational content.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Tech Innovation
|
|
2
|
+
|
|
3
|
+
A bold and modern theme with high-contrast colors perfect for cutting-edge technology presentations.
|
|
4
|
+
|
|
5
|
+
## Color Palette
|
|
6
|
+
|
|
7
|
+
- **Electric Blue**: `#0066ff` - Vibrant primary accent
|
|
8
|
+
- **Neon Cyan**: `#00ffff` - Bright highlight color
|
|
9
|
+
- **Dark Gray**: `#1e1e1e` - Deep backgrounds
|
|
10
|
+
- **White**: `#ffffff` - Clean text and contrast
|
|
11
|
+
|
|
12
|
+
## Typography
|
|
13
|
+
|
|
14
|
+
- **Headers**: DejaVu Sans Bold
|
|
15
|
+
- **Body Text**: DejaVu Sans
|
|
16
|
+
|
|
17
|
+
## Best Used For
|
|
18
|
+
|
|
19
|
+
Tech startups, software launches, innovation showcases, AI/ML presentations, digital transformation content.
|