diff --git a/pyproject.toml b/pyproject.toml index 3574d16e..ca17c841 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,7 @@ dependencies = [ "selenium", "twine", "wheel", + "pyppeteer", # to generate icons with oca-gen-addon-icon "pyproject_dependencies ; python_version>='3.7'", "setuptools-odoo", # for oca-gen-external-dependencies "whool", # for oca-gen-external-dependencies diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..9d29583c --- /dev/null +++ b/setup.py @@ -0,0 +1,86 @@ +# License AGPLv3 (https://www.gnu.org/licenses/agpl-3.0-standalone.html) +import os +import setuptools + + +here = os.path.dirname(os.path.abspath(__file__)) +with open(os.path.join(here, "README.md")) as f: + long_description = f.read() + + +setuptools.setup( + name="oca-maintainers-tools", + author="Odoo Community Association (OCA)", + description="Set of tools to help managing Odoo Community projects", + long_description=long_description, + license="AGPL3", + packages=["tools"], + include_package_data=True, + zip_safe=False, + use_scm_version=True, + setup_requires=[ + "setuptools_scm", + ], + install_requires=[ + "appdirs", + "click", + "docutils", + "pypandoc", # for oca-gen-addon-readme to work with markdown fragments + "ERPpeek", + "freezegun", + "github3.py>=1", + "jinja2", + "manifestoo-core>=1.1", + "PyYAML", + "polib", + "pygments", + "requests", + "toml>=0.10.0", # for oca-towncrier + "tomli ; python_version < '3.11'", # from 3.11 tomllib is in stdlib + "towncrier>=21.3", # for oca-towncrier + "selenium", + "twine", + "wheel", + "pyproject_dependencies ; python_version>='3.7'", + "setuptools-odoo", # for oca-gen-external-dependencies + "whool", # for oca-gen-external-dependencies + "pyppeteer", # to generate icons with oca-gen-addon-icon + ], + python_requires=">=3.6", + classifiers=[ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: " + "GNU Affero General Public License v3 or later (AGPLv3+)", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + ], + entry_points={ + "console_scripts": [ + "oca-github-login = tools.github_login:main", + "oca-copy-maintainers = tools.copy_maintainers:main", + "oca-clone-everything = tools.clone_everything:main", + "oca-set-repo-labels = tools.set_repo_labels:main", + "oca-odoo-login = tools.odoo_login:main", + "oca-sync-users = tools.oca_sync_users:main", + "oca-gen-addons-table = tools.gen_addons_table:gen_addons_table", + "oca-migrate-branch = tools.migrate_branch:main", + "oca-migrate-branch-empty = tools.migrate_branch_empty:main", + "oca-publish-modules = tools.publish_modules:main", + "oca-gen-addon-readme = tools.gen_addon_readme:gen_addon_readme", + "oca-gen-addon-icon = tools.gen_addon_icon:gen_addon_icon", + "oca-gen-external-dependencies = tools.gen_external_dependencies:main", + "oca-gen-metapackage = tools.gen_metapackage:main", + "oca-towncrier = tools.oca_towncrier:oca_towncrier", + "oca-create-migration-issue = tools.create_migration_issue:main", + "oca-update-pre-commit-excluded-addons = " + "tools.update_pre_commit_excluded_addons:main", + "oca-fix-manifest-website = tools.fix_manifest_website:main", + "oca-configure-travis= tools.configure_travis:main", + "oca-create-branch = tools.create_branch:main", + "oca-copier-update = tools.copier_update:main", + ], + }, +) diff --git a/tools/gen_addon_icon.css b/tools/gen_addon_icon.css new file mode 100644 index 00000000..29f3f780 --- /dev/null +++ b/tools/gen_addon_icon.css @@ -0,0 +1,331 @@ +html { + text-align: center; + background-color: transparent; + height: 100%; + -webkit-print-color-adjust: exact; +} + +body { + width: 140px; + height: 140px; + background: transparent; +} + +.icon-box { + position: relative; + text-align: center; + overflow: hidden; + width: 140px; + height: 140px; + font-size: 90px; + line-height: 120px; + border-radius: 6px; + padding: 0; +} + +.icon-box:before { + content: ""; + display: block; + position: absolute; + width: 100%; + height: 100%; + box-shadow: inset 0 1px 0px 0px rgba(255, 255, 255, 0.38), inset 0 -1px 0px 0px rgba(0, 0, 0, 0.38); + -webkit-box-shadow: inset 0 1px 0px 0px rgba(255, 255, 255, 0.38), inset 0 -1px 0px 0px rgba(0, 0, 0, 0.38); +} + +.icon-box span { + display: block; + height: 140px; + width: 140px; + color: #fff; + padding: 15; + z-index: 999; +} + +.oorange { + background: linear-gradient(45deg, #cc7039, #da956b); + border-top-color: #e7bba2; + border-bottom-color: #643f2a; +} + +.opink { + background: linear-gradient(45deg, #ca5377, #cd7690); + border-top-color: #dfa2b4; + border-bottom-color: #623241; +} + +.oyellow { + background: linear-gradient(45deg, #b5aa59, #cdc484); + border-top-color: #ddd8b1; + border-bottom-color: #5b5739; +} + +.ogray { + background: linear-gradient(45deg, #545554, #797c79); + border-bottom-color: #a5a7a5; + border-bottom-color: #3a3a3a; +} + +.oteal { + background: linear-gradient(45deg, #218689, #269396); + border-bottom-color: #175557; + border-top-color: #78b9ba; +} + +.oblue1 { + background: linear-gradient(45deg, #6a9eba, #94b6c8); + border-top-color: #bbd1dc; + border-bottom-color: #3d515c; +} + +.oblue2 { + background: linear-gradient(45deg, #626584, #797da5); + border-top-color: #aaacc3; + border-bottom-color: #373946; +} + +.ored { + background: linear-gradient(45deg, #7c3838, #b06161); + border-top-color: #c19393; + border-bottom-color: #462727; +} + +.ogreen { + background: linear-gradient(45deg, #5f8a71, #7cc098); + border-top-color: #abd1bb; + border-bottom-color: #374c41; +} + +.oorange span { + text-shadow: #a16542 -1px 1px, #a16542 -2px 2px, #a16542 -3px 3px, + #a16542 -4px 4px, #a16542 -5px 5px, #a16542 -6px 6px, #a16542 -7px 7px, + #a16542 -8px 8px, #a16542 -9px 9px, #a16542 -10px 10px, #a16542 -11px 11px, + #a16542 -12px 12px, #a16542 -13px 13px, #a16542 -14px 14px, + #a16542 -15px 15px, #a16542 -16px 16px, #a16542 -17px 17px, + #a16542 -18px 18px, #a16542 -19px 19px, #a16542 -20px 20px, + #a16542 -21px 21px, #a16542 -22px 22px, #a16542 -23px 23px, + #a16542 -24px 24px, #a16542 -25px 25px, #a16542 -26px 26px, + #a16542 -27px 27px, #a16542 -28px 28px, #a16542 -29px 29px, + #a16542 -30px 30px, #a16542 -31px 31px, #a16542 -32px 32px, + #a16542 -33px 33px, #a16542 -34px 34px, #a16542 -35px 35px, + #a16542 -36px 36px, #a16542 -37px 37px, #a16542 -38px 38px, + #a16542 -39px 39px, #a16542 -40px 40px, #a16542 -41px 41px, + #a16542 -42px 42px, #a16542 -43px 43px, #a16542 -44px 44px, + #a16542 -45px 45px, #a16542 -46px 46px, #a16542 -47px 47px, + #a16542 -48px 48px, #a16542 -49px 49px, #a16542 -50px 50px, + #a16542 -51px 51px, #a16542 -52px 52px, #a16542 -53px 53px, + #a16542 -54px 54px, #a16542 -55px 55px, #a16542 -56px 56px, + #a16542 -57px 57px, #a16542 -58px 58px, #a16542 -59px 59px, + #a16542 -60px 60px, #a16542 -61px 61px, #a16542 -62px 62px, + #a16542 -63px 63px, #a16542 -64px 64px, #a16542 -65px 65px, + #a16542 -66px 66px, #a16542 -67px 67px, #a16542 -68px 68px, + #a16542 -69px 69px, #a16542 -70px 70px; +} + +.opink span { + text-shadow: #9e5168 -1px 1px, #9e5168 -2px 2px, #9e5168 -3px 3px, + #9e5168 -4px 4px, #9e5168 -5px 5px, #9e5168 -6px 6px, #9e5168 -7px 7px, + #9e5168 -8px 8px, #9e5168 -9px 9px, #9e5168 -10px 10px, #9e5168 -11px 11px, + #9e5168 -12px 12px, #9e5168 -13px 13px, #9e5168 -14px 14px, + #9e5168 -15px 15px, #9e5168 -16px 16px, #9e5168 -17px 17px, + #9e5168 -18px 18px, #9e5168 -19px 19px, #9e5168 -20px 20px, + #9e5168 -21px 21px, #9e5168 -22px 22px, #9e5168 -23px 23px, + #9e5168 -24px 24px, #9e5168 -25px 25px, #9e5168 -26px 26px, + #9e5168 -27px 27px, #9e5168 -28px 28px, #9e5168 -29px 29px, + #9e5168 -30px 30px, #9e5168 -31px 31px, #9e5168 -32px 32px, + #9e5168 -33px 33px, #9e5168 -34px 34px, #9e5168 -35px 35px, + #9e5168 -36px 36px, #9e5168 -37px 37px, #9e5168 -38px 38px, + #9e5168 -39px 39px, #9e5168 -40px 40px, #9e5168 -41px 41px, + #9e5168 -42px 42px, #9e5168 -43px 43px, #9e5168 -44px 44px, + #9e5168 -45px 45px, #9e5168 -46px 46px, #9e5168 -47px 47px, + #9e5168 -48px 48px, #9e5168 -49px 49px, #9e5168 -50px 50px, + #9e5168 -51px 51px, #9e5168 -52px 52px, #9e5168 -53px 53px, + #9e5168 -54px 54px, #9e5168 -55px 55px, #9e5168 -56px 56px, + #9e5168 -57px 57px, #9e5168 -58px 58px, #9e5168 -59px 59px, + #9e5168 -60px 60px, #9e5168 -61px 61px, #9e5168 -62px 62px, + #9e5168 -63px 63px, #9e5168 -64px 64px, #9e5168 -65px 65px, + #9e5168 -66px 66px, #9e5168 -67px 67px, #9e5168 -68px 68px, + #9e5168 -69px 69px, #9e5168 -70px 70px; +} + +.oyellow span { + text-shadow: #938c57 -1px 1px, #938c57 -2px 2px, #938c57 -3px 3px, + #938c57 -4px 4px, #938c57 -5px 5px, #938c57 -6px 6px, #938c57 -7px 7px, + #938c57 -8px 8px, #938c57 -9px 9px, #938c57 -10px 10px, #938c57 -11px 11px, + #938c57 -12px 12px, #938c57 -13px 13px, #938c57 -14px 14px, + #938c57 -15px 15px, #938c57 -16px 16px, #938c57 -17px 17px, + #938c57 -18px 18px, #938c57 -19px 19px, #938c57 -20px 20px, + #938c57 -21px 21px, #938c57 -22px 22px, #938c57 -23px 23px, + #938c57 -24px 24px, #938c57 -25px 25px, #938c57 -26px 26px, + #938c57 -27px 27px, #938c57 -28px 28px, #938c57 -29px 29px, + #938c57 -30px 30px, #938c57 -31px 31px, #938c57 -32px 32px, + #938c57 -33px 33px, #938c57 -34px 34px, #938c57 -35px 35px, + #938c57 -36px 36px, #938c57 -37px 37px, #938c57 -38px 38px, + #938c57 -39px 39px, #938c57 -40px 40px, #938c57 -41px 41px, + #938c57 -42px 42px, #938c57 -43px 43px, #938c57 -44px 44px, + #938c57 -45px 45px, #938c57 -46px 46px, #938c57 -47px 47px, + #938c57 -48px 48px, #938c57 -49px 49px, #938c57 -50px 50px, + #938c57 -51px 51px, #938c57 -52px 52px, #938c57 -53px 53px, + #938c57 -54px 54px, #938c57 -55px 55px, #938c57 -56px 56px, + #938c57 -57px 57px, #938c57 -58px 58px, #938c57 -59px 59px, + #938c57 -60px 60px, #938c57 -61px 61px, #938c57 -62px 62px, + #938c57 -63px 63px, #938c57 -64px 64px, #938c57 -65px 65px, + #938c57 -66px 66px, #938c57 -67px 67px, #938c57 -68px 68px, + #938c57 -69px 69px, #938c57 -70px 70px; +} + +.ogray span { + text-shadow: #525352 -1px 1px, #525352 -2px 2px, #525352 -3px 3px, + #525352 -4px 4px, #525352 -5px 5px, #525352 -6px 6px, #525352 -7px 7px, + #525352 -8px 8px, #525352 -9px 9px, #525352 -10px 10px, #525352 -11px 11px, + #525352 -12px 12px, #525352 -13px 13px, #525352 -14px 14px, + #525352 -15px 15px, #525352 -16px 16px, #525352 -17px 17px, + #525352 -18px 18px, #525352 -19px 19px, #525352 -20px 20px, + #525352 -21px 21px, #525352 -22px 22px, #525352 -23px 23px, + #525352 -24px 24px, #525352 -25px 25px, #525352 -26px 26px, + #525352 -27px 27px, #525352 -28px 28px, #525352 -29px 29px, + #525352 -30px 30px, #525352 -31px 31px, #525352 -32px 32px, + #525352 -33px 33px, #525352 -34px 34px, #525352 -35px 35px, + #525352 -36px 36px, #525352 -37px 37px, #525352 -38px 38px, + #525352 -39px 39px, #525352 -40px 40px, #525352 -41px 41px, + #525352 -42px 42px, #525352 -43px 43px, #525352 -44px 44px, + #525352 -45px 45px, #525352 -46px 46px, #525352 -47px 47px, + #525352 -48px 48px, #525352 -49px 49px, #525352 -50px 50px, + #525352 -51px 51px, #525352 -52px 52px, #525352 -53px 53px, + #525352 -54px 54px, #525352 -55px 55px, #525352 -56px 56px, + #525352 -57px 57px, #525352 -58px 58px, #525352 -59px 59px, + #525352 -60px 60px, #525352 -61px 61px, #525352 -62px 62px, + #525352 -63px 63px, #525352 -64px 64px, #525352 -65px 65px, + #525352 -66px 66px, #525352 -67px 67px, #525352 -68px 68px, + #525352 -69px 69px, #525352 -70px 70px; +} + +.oteal span { + text-shadow: #297072 -1px 1px, #297072 -2px 2px, #297072 -3px 3px, + #297072 -4px 4px, #297072 -5px 5px, #297072 -6px 6px, #297072 -7px 7px, + #297072 -8px 8px, #297072 -9px 9px, #297072 -10px 10px, #297072 -11px 11px, + #297072 -12px 12px, #297072 -13px 13px, #297072 -14px 14px, + #297072 -15px 15px, #297072 -16px 16px, #297072 -17px 17px, + #297072 -18px 18px, #297072 -19px 19px, #297072 -20px 20px, + #297072 -21px 21px, #297072 -22px 22px, #297072 -23px 23px, + #297072 -24px 24px, #297072 -25px 25px, #297072 -26px 26px, + #297072 -27px 27px, #297072 -28px 28px, #297072 -29px 29px, + #297072 -30px 30px, #297072 -31px 31px, #297072 -32px 32px, + #297072 -33px 33px, #297072 -34px 34px, #297072 -35px 35px, + #297072 -36px 36px, #297072 -37px 37px, #297072 -38px 38px, + #297072 -39px 39px, #297072 -40px 40px, #297072 -41px 41px, + #297072 -42px 42px, #297072 -43px 43px, #297072 -44px 44px, + #297072 -45px 45px, #297072 -46px 46px, #297072 -47px 47px, + #297072 -48px 48px, #297072 -49px 49px, #297072 -50px 50px, + #297072 -51px 51px, #297072 -52px 52px, #297072 -53px 53px, + #297072 -54px 54px, #297072 -55px 55px, #297072 -56px 56px, + #297072 -57px 57px, #297072 -58px 58px, #297072 -59px 59px, + #297072 -60px 60px, #297072 -61px 61px, #297072 -62px 62px, + #297072 -63px 63px, #297072 -64px 64px, #297072 -65px 65px, + #297072 -66px 66px, #297072 -67px 67px, #297072 -68px 68px, + #297072 -69px 69px, #297072 -70px 70px; +} + +.oblue1 span { + text-shadow: #628395 -1px 1px, #628395 -2px 2px, #628395 -3px 3px, + #628395 -4px 4px, #628395 -5px 5px, #628395 -6px 6px, #628395 -7px 7px, + #628395 -8px 8px, #628395 -9px 9px, #628395 -10px 10px, #628395 -11px 11px, + #628395 -12px 12px, #628395 -13px 13px, #628395 -14px 14px, + #628395 -15px 15px, #628395 -16px 16px, #628395 -17px 17px, + #628395 -18px 18px, #628395 -19px 19px, #628395 -20px 20px, + #628395 -21px 21px, #628395 -22px 22px, #628395 -23px 23px, + #628395 -24px 24px, #628395 -25px 25px, #628395 -26px 26px, + #628395 -27px 27px, #628395 -28px 28px, #628395 -29px 29px, + #628395 -30px 30px, #628395 -31px 31px, #628395 -32px 32px, + #628395 -33px 33px, #628395 -34px 34px, #628395 -35px 35px, + #628395 -36px 36px, #628395 -37px 37px, #628395 -38px 38px, + #628395 -39px 39px, #628395 -40px 40px, #628395 -41px 41px, + #628395 -42px 42px, #628395 -43px 43px, #628395 -44px 44px, + #628395 -45px 45px, #628395 -46px 46px, #628395 -47px 47px, + #628395 -48px 48px, #628395 -49px 49px, #628395 -50px 50px, + #628395 -51px 51px, #628395 -52px 52px, #628395 -53px 53px, + #628395 -54px 54px, #628395 -55px 55px, #628395 -56px 56px, + #628395 -57px 57px, #628395 -58px 58px, #628395 -59px 59px, + #628395 -60px 60px, #628395 -61px 61px, #628395 -62px 62px, + #628395 -63px 63px, #628395 -64px 64px, #628395 -65px 65px, + #628395 -66px 66px, #628395 -67px 67px, #628395 -68px 68px, + #628395 -69px 69px, #628395 -70px 70px; +} + +.oblue2 span { + text-shadow: #595c72 -1px 1px, #595c72 -2px 2px, #595c72 -3px 3px, + #595c72 -4px 4px, #595c72 -5px 5px, #595c72 -6px 6px, #595c72 -7px 7px, + #595c72 -8px 8px, #595c72 -9px 9px, #595c72 -10px 10px, #595c72 -11px 11px, + #595c72 -12px 12px, #595c72 -13px 13px, #595c72 -14px 14px, + #595c72 -15px 15px, #595c72 -16px 16px, #595c72 -17px 17px, + #595c72 -18px 18px, #595c72 -19px 19px, #595c72 -20px 20px, + #595c72 -21px 21px, #595c72 -22px 22px, #595c72 -23px 23px, + #595c72 -24px 24px, #595c72 -25px 25px, #595c72 -26px 26px, + #595c72 -27px 27px, #595c72 -28px 28px, #595c72 -29px 29px, + #595c72 -30px 30px, #595c72 -31px 31px, #595c72 -32px 32px, + #595c72 -33px 33px, #595c72 -34px 34px, #595c72 -35px 35px, + #595c72 -36px 36px, #595c72 -37px 37px, #595c72 -38px 38px, + #595c72 -39px 39px, #595c72 -40px 40px, #595c72 -41px 41px, + #595c72 -42px 42px, #595c72 -43px 43px, #595c72 -44px 44px, + #595c72 -45px 45px, #595c72 -46px 46px, #595c72 -47px 47px, + #595c72 -48px 48px, #595c72 -49px 49px, #595c72 -50px 50px, + #595c72 -51px 51px, #595c72 -52px 52px, #595c72 -53px 53px, + #595c72 -54px 54px, #595c72 -55px 55px, #595c72 -56px 56px, + #595c72 -57px 57px, #595c72 -58px 58px, #595c72 -59px 59px, + #595c72 -60px 60px, #595c72 -61px 61px, #595c72 -62px 62px, + #595c72 -63px 63px, #595c72 -64px 64px, #595c72 -65px 65px, + #595c72 -66px 66px, #595c72 -67px 67px, #595c72 -68px 68px, + #595c72 -69px 69px, #595c72 -70px 70px; +} + +.ored span { + text-shadow: #703f3f -1px 1px, #703f3f -2px 2px, #703f3f -3px 3px, + #703f3f -4px 4px, #703f3f -5px 5px, #703f3f -6px 6px, #703f3f -7px 7px, + #703f3f -8px 8px, #703f3f -9px 9px, #703f3f -10px 10px, #703f3f -11px 11px, + #703f3f -12px 12px, #703f3f -13px 13px, #703f3f -14px 14px, + #703f3f -15px 15px, #703f3f -16px 16px, #703f3f -17px 17px, + #703f3f -18px 18px, #703f3f -19px 19px, #703f3f -20px 20px, + #703f3f -21px 21px, #703f3f -22px 22px, #703f3f -23px 23px, + #703f3f -24px 24px, #703f3f -25px 25px, #703f3f -26px 26px, + #703f3f -27px 27px, #703f3f -28px 28px, #703f3f -29px 29px, + #703f3f -30px 30px, #703f3f -31px 31px, #703f3f -32px 32px, + #703f3f -33px 33px, #703f3f -34px 34px, #703f3f -35px 35px, + #703f3f -36px 36px, #703f3f -37px 37px, #703f3f -38px 38px, + #703f3f -39px 39px, #703f3f -40px 40px, #703f3f -41px 41px, + #703f3f -42px 42px, #703f3f -43px 43px, #703f3f -44px 44px, + #703f3f -45px 45px, #703f3f -46px 46px, #703f3f -47px 47px, + #703f3f -48px 48px, #703f3f -49px 49px, #703f3f -50px 50px, + #703f3f -51px 51px, #703f3f -52px 52px, #703f3f -53px 53px, + #703f3f -54px 54px, #703f3f -55px 55px, #703f3f -56px 56px, + #703f3f -57px 57px, #703f3f -58px 58px, #703f3f -59px 59px, + #703f3f -60px 60px, #703f3f -61px 61px, #703f3f -62px 62px, + #703f3f -63px 63px, #703f3f -64px 64px, #703f3f -65px 65px, + #703f3f -66px 66px, #703f3f -67px 67px, #703f3f -68px 68px, + #703f3f -69px 69px, #703f3f -70px 70px; +} + +.ogreen span { + text-shadow: #587b67 -1px 1px, #587b67 -2px 2px, #587b67 -3px 3px, + #587b67 -4px 4px, #587b67 -5px 5px, #587b67 -6px 6px, #587b67 -7px 7px, + #587b67 -8px 8px, #587b67 -9px 9px, #587b67 -10px 10px, #587b67 -11px 11px, + #587b67 -12px 12px, #587b67 -13px 13px, #587b67 -14px 14px, + #587b67 -15px 15px, #587b67 -16px 16px, #587b67 -17px 17px, + #587b67 -18px 18px, #587b67 -19px 19px, #587b67 -20px 20px, + #587b67 -21px 21px, #587b67 -22px 22px, #587b67 -23px 23px, + #587b67 -24px 24px, #587b67 -25px 25px, #587b67 -26px 26px, + #587b67 -27px 27px, #587b67 -28px 28px, #587b67 -29px 29px, + #587b67 -30px 30px, #587b67 -31px 31px, #587b67 -32px 32px, + #587b67 -33px 33px, #587b67 -34px 34px, #587b67 -35px 35px, + #587b67 -36px 36px, #587b67 -37px 37px, #587b67 -38px 38px, + #587b67 -39px 39px, #587b67 -40px 40px, #587b67 -41px 41px, + #587b67 -42px 42px, #587b67 -43px 43px, #587b67 -44px 44px, + #587b67 -45px 45px, #587b67 -46px 46px, #587b67 -47px 47px, + #587b67 -48px 48px, #587b67 -49px 49px, #587b67 -50px 50px, + #587b67 -51px 51px, #587b67 -52px 52px, #587b67 -53px 53px, + #587b67 -54px 54px, #587b67 -55px 55px, #587b67 -56px 56px, + #587b67 -57px 57px, #587b67 -58px 58px, #587b67 -59px 59px, + #587b67 -60px 60px, #587b67 -61px 61px, #587b67 -62px 62px, + #587b67 -63px 63px, #587b67 -64px 64px, #587b67 -65px 65px, + #587b67 -66px 66px, #587b67 -67px 67px, #587b67 -68px 68px, + #587b67 -69px 69px, #587b67 -70px 70px; +} diff --git a/tools/gen_addon_icon.py b/tools/gen_addon_icon.py index e76596ee..0aaf296c 100644 --- a/tools/gen_addon_icon.py +++ b/tools/gen_addon_icon.py @@ -4,8 +4,11 @@ import os import shutil - +import json +import asyncio import click +from pyppeteer import launch +from string import Template from .gitutils import commit_if_needed from .manifest import NoManifestFound, find_addons, read_manifest @@ -14,7 +17,37 @@ ICON_TYPE = "png" -ICON_TYPES = ["png", "svg"] +ICON_TYPES = ["png", "svg", "pdf"] + +COLORS = ["orange", "pink", "yellow", "gray", "teal", "blue1", "blue2", "red", "green"] + +SUPPORTED_SERVICE_URLS = [ + "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css", # noqa + "https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.5.5/css/simple-line-icons.min.css", # noqa + "https://cdnjs.cloudflare.com/ajax/libs/open-iconic/1.1.1/font/css/open-iconic.min.css", # noqa + "https://cdnjs.cloudflare.com/ajax/libs/material-design-icons/3.0.2/iconfont/material-icons.min.css", # noqa + "https://cdnjs.cloudflare.com/ajax/libs/tabler-icons/1.35.0/iconfont/tabler-icons.min.css", # noqa + "https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.12/css/weather-icons.min.css", # noqa + "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css", # noqa + "https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css", # noqa + "https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css", # noqa + "https://www.experimentalenhancements.com/FontCountry/FontCountry.css", # noqa +] + +TEMPLATE = Template( + """ + + +
+ + + $icon_extra + +
+ + +""" +) def gen_one_addon_icon(icon_dir, src_icon=None, filetype=ICON_TYPE): @@ -35,6 +68,121 @@ def gen_one_addon_icon(icon_dir, src_icon=None, filetype=ICON_TYPE): return None +def _prepare_extra_icon_html(icon_extra): + if not icon_extra: + return "" + icon_extra = json.loads(icon_extra.replace("'", '"')) + extra_styles = {"top", "left", "shadow", "color", "position", "font-size"} + icon_extra_html = "" + for icon, params in icon_extra.items(): + params.setdefault("color", "white") + params.setdefault("position", "absolute") + params.setdefault("font-size", "90px") + params.setdefault("top", "15px") + params.setdefault("left", "20px") + style = [ + "{}: {}".format(x, params[x]) for x in extra_styles if x in params.keys() + ] + icon_extra_html += """ + + """.format(icon, ";".join(style)) + return icon_extra_html + + +minimal_args = [ + "--autoplay-policy=user-gesture-required", + "--disable-background-networking", + "--disable-background-timer-throttling", + "--disable-backgrounding-occluded-windows", + "--disable-breakpad", + "--disable-default-apps", + "--disable-dev-shm-usage", + "--disable-domain-reliability", + "--disable-extensions", + "--disable-features=AudioServiceOutOfProcess", + "--disable-hang-monitor", + "--disable-ipc-flooding-protection", + "--disable-notifications", + "--disable-offer-store-unmasked-wallet-cards", + "--disable-popup-blocking", + "--disable-print-preview", + "--disable-prompt-on-repost", + "--disable-renderer-backgrounding", + "--disable-setuid-sandbox", + "--disable-speech-api", + "--disable-sync", + "--hide-scrollbars", + "--ignore-gpu-blacklist", + "--metrics-recording-only", + "--mute-audio", + "--no-default-browser-check", + "--no-first-run", + "--no-pings", + "--no-sandbox", + "--no-zygote", + "--password-store=basic", +] + + +async def generate_template_screenshot(template, options, filetype): + """Generate custom icon with chromium headless""" + styles_filename = os.path.join(os.path.dirname(__file__), "gen_addon_icon.css") + browser = await launch(headless=True, args=minimal_args) + page = await browser.newPage() + await page.goto( + "data:text/html,{}".format(template), {"waitUntil": "domcontentloaded"} + ) + for url in SUPPORTED_SERVICE_URLS: + await page.addStyleTag({"url": url}) + await page.addStyleTag({"path": styles_filename}) + await page.emulateMedia("screen") + await page.mouse.click( + 0, 0, {"delay": 500} + ) # hack to wait until icons are displayed + if filetype in ["png", "jpg"]: + await page.screenshot(options) + else: + await page.pdf(options) + await browser.close() + + +def gen_special_addon_icon(icon_dir, icon_set_params, icon_color, icon_extra, filetype): + """Generate icons using popular icon libraries like fontawesome, etc""" + icon_filename = os.path.join(icon_dir, "icon.%s" % filetype) + if filetype in ["png", "jpg"]: + options = { + "path": icon_filename, + "omitBackground": True, + "quality": 100, + "clip": { + "y": 0, + "x": 0, + "width": 140, + "height": 140, + }, + } + else: + options = { + "path": icon_filename, + "width": 140, + "height": 140, + "printBackground": False, + "omitBackground": True, + "scale": 1, + } + template = TEMPLATE.substitute( + icon_set_params=icon_set_params, + icon_color=icon_color, + icon_extra=_prepare_extra_icon_html(icon_extra), + ) + if not os.path.exists(icon_dir): + os.makedirs(icon_dir) + asyncio.get_event_loop().run_until_complete( + generate_template_screenshot(template, options, filetype) + ) + return icon_filename + + @click.command() @click.option( "--addon-dir", @@ -49,14 +197,17 @@ def gen_one_addon_icon(icon_dir, src_icon=None, filetype=ICON_TYPE): help="Directory containing several addons, the icon will be " "put for all installable addons found there.", ) +@click.option("--commit/--no-commit", help="git commit icon, if not any.") +@click.option("--icon-set-params", help="Use this set to generate an automatic icon") @click.option( - "--src-icon", - type=click.Path(dir_okay=False, file_okay=True, exists=True), - help="Path to a custom icon.png file. If not set, it'll use the " - "OCA template icon.", + "--icon-color", + help="Options: orange, pink, yellow, gray, teal, " "blue1, blue2, red, green", ) -@click.option("--commit/--no-commit", help="git commit icon, if not any.") -def gen_addon_icon(addon_dirs, addons_dir, src_icon, commit): +@click.option("--icon-extra", help="Extra icons to overlap") +@click.option("--format", help="Icon format, you can choose between png or pdf") +def gen_addon_icon( + addon_dirs, addons_dir, commit, icon_set_params, icon_color, icon_extra, format +): """Put default OCA icon of type ICON_TYPE. Do nothing if the icon already exists in ICONS_DIR, otherwise put @@ -84,11 +235,25 @@ def gen_addon_icon(addon_dirs, addons_dir, src_icon, commit): # icon was created manually exist = True break - if exist: + if exist and not icon_set_params and not icon_extra: continue - icon_filename = gen_one_addon_icon(icon_dir, src_icon=src_icon) + if icon_set_params or icon_extra: + # Apply some default so we can just put the icon params + icon_color = icon_color or "teal" + if format not in ICON_TYPES: + format = "png" + icon_filename = gen_special_addon_icon( + icon_dir, + icon_set_params=icon_set_params, + icon_color=icon_color, + icon_extra=icon_extra, + filetype=format, + ) + else: + icon_filename = gen_one_addon_icon(icon_dir) if icon_filename: icon_filenames.append(icon_filename) + if icon_filenames and commit: commit_if_needed(icon_filenames, "[ADD] icon.%s" % ICON_TYPE) diff --git a/tools/gen_addon_icon_template.html b/tools/gen_addon_icon_template.html new file mode 100644 index 00000000..a9377ad3 --- /dev/null +++ b/tools/gen_addon_icon_template.html @@ -0,0 +1,34 @@ + + + + + + + +
+ +
+ +