diff options
Diffstat (limited to 'toolkit/content/widgets/mach_commands.py')
-rw-r--r-- | toolkit/content/widgets/mach_commands.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/toolkit/content/widgets/mach_commands.py b/toolkit/content/widgets/mach_commands.py new file mode 100644 index 0000000000..2bc6044e24 --- /dev/null +++ b/toolkit/content/widgets/mach_commands.py @@ -0,0 +1,164 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import re + +from mach.decorators import Command, CommandArgument + +LICENSE_HEADER = """/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +""" + +JS_HEADER = """{license} +import {{ html }} from "../vendor/lit.all.mjs"; +import {{ MozLitElement }} from "../lit-utils.mjs"; + +/** + * Component description goes here. + * + * @tagname {element_name} + * @property {{string}} variant - Property description goes here + */ +export default class {class_name} extends MozLitElement {{ + static properties = {{ + variant: {{ type: String }}, + }}; + + // Use a relative URL in storybook to get faster reloads on style changes. + static stylesheetUrl = window.IS_STORYBOOK + ? "./{element_name}/{element_name}.css" + : "chrome://global/content/elements/{element_name}.css"; + + constructor() {{ + super(); + this.variant = "default"; + }} + + render() {{ + return html` + <link rel="stylesheet" href=${{this.constructor.stylesheetUrl}} /> + <div>Variant type: ${{this.variant}}</div> + `; + }} +}} +customElements.define("{element_name}", {class_name}); +""" + +STORY_HEADER = """{license} +import {{ html }} from "../vendor/lit.all.mjs"; +// eslint-disable-next-line import/no-unassigned-import +import "./{element_name}.mjs"; + +export default {{ + title: "UI Widgets/{story_name}", + component: "{element_name}", + argTypes: {{ + variant: {{ + options: ["default", "other"], + control: {{ type: "select" }}, + }}, + }}, +}}; + +const Template = ({{ variant }}) => html` + <{element_name} .variant=${{variant}}></{element_name}> +`; + +export const Default = Template.bind({{}}); +Default.args = {{ + variant: "default", +}}; +""" + + +def run_mach(command_context, cmd, **kwargs): + return command_context._mach_context.commands.dispatch( + cmd, command_context._mach_context, **kwargs + ) + + +def run_npm(command_context, args): + return run_mach( + command_context, "npm", args=[*args, "--prefix=browser/components/storybook"] + ) + + +@Command( + "addwidget", + category="misc", + description="Scaffold a front-end component.", +) +@CommandArgument( + "names", + nargs="+", + help="Component names to create in kebab-case, eg. my-card.", +) +def addwidget(command_context, names): + for name in names: + component_dir = "toolkit/content/widgets/{0}".format(name) + + try: + os.mkdir(component_dir) + except FileExistsError: + pass + + with open("{0}/{1}.mjs".format(component_dir, name), "w", newline="\n") as f: + class_name = "".join(p.capitalize() for p in name.split("-")) + f.write( + JS_HEADER.format( + license=LICENSE_HEADER, + element_name=name, + class_name=class_name, + ) + ) + + with open("{0}/{1}.css".format(component_dir, name), "w", newline="\n") as f: + f.write(LICENSE_HEADER) + + test_name = name.replace("-", "_") + test_path = "toolkit/content/tests/widgets/test_{0}.html".format(test_name) + jar_path = "toolkit/content/jar.mn" + jar_lines = None + with open(jar_path, "r") as f: + jar_lines = f.readlines() + elements_startswith = " content/global/elements/" + new_css_line = "{0}{1}.css (widgets/{1}/{1}.css)\n".format( + elements_startswith, name + ) + new_js_line = "{0}{1}.mjs (widgets/{1}/{1}.mjs)\n".format( + elements_startswith, name + ) + new_jar_lines = [] + found_elements_section = False + added_widget = False + for line in jar_lines: + if line.startswith(elements_startswith): + found_elements_section = True + if found_elements_section and not added_widget and line > new_css_line: + added_widget = True + new_jar_lines.append(new_css_line) + new_jar_lines.append(new_js_line) + new_jar_lines.append(line) + + with open(jar_path, "w", newline="\n") as f: + f.write("".join(new_jar_lines)) + + story_path = "{0}/{1}.stories.mjs".format(component_dir, name) + with open(story_path, "w", newline="\n") as f: + story_name = " ".join( + name for name in re.findall(r"[A-Z][a-z]+", class_name) if name != "Moz" + ) + f.write( + STORY_HEADER.format( + license=LICENSE_HEADER, + element_name=name, + story_name=story_name, + ) + ) + + run_mach( + command_context, "addtest", argv=[test_path, "--suite", "mochitest-chrome"] + ) |