# 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 from mach.util import UserError
FIXME_COMMENT = "// FIXME: replace with path to your reusable widget\n"
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/. */ """
def parse_acorn_elements(file_path): with open(file_path, newline="\n") as file:
content = file.read()
# Regex to extract elements from the acornElements array
pattern = r'\[\s*"([^"]+)"\s*,\s*"([^"]+)"\s*,?\s*\]'
matches = re.findall(pattern, content, flags=re.DOTALL)
# Filter out tags that don't start with "moz-"
filtered = [match for match in matches if match[0].startswith("moz-")]
return filtered # List of (tag, path tuples)
def add_sorted_entry(elements, new_tag, new_path): ifnot any(tag == new_tag for tag, _ in elements):
elements.append((new_tag, new_path))
elements.sort(key=lambda x: x[0]) return elements
def update_acorn_elements_in_file(file_path, updated_elements): with open(file_path, newline="\n") as file:
lines = file.readlines() # Locate the start and end of the acornElements array
start_id = None
end_id = None for i, line in enumerate(lines): if"let acornElements = ["in line:
start_id = i if start_id isnotNoneand line.strip() == "];":
end_id = i if start_id isnotNoneand end_id isnotNone: break if start_id isNone: raise ValueError("Could not find 'let acornElements = [' in customElements.js.") if end_id isNone: raise ValueError( "Could not find a closing bracket to 'let acornElements = [' in customElements.js."
) # Build updated array block
array_lines = ["let acornElements = [\n"] for tag, path in updated_elements:
array_lines.append(f' ["{tag}", "{path}"],\n')
array_lines.append("];\n")
# Replace old array block with new one
new_lines = lines[:start_id] + array_lines + lines[end_id + 1 :]
with open(file_path, "w", newline="\n") as file:
file.writelines(new_lines)
@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):
story_prefix = "UI Widgets"
html_lit_import = 'import { html } from "../vendor/lit.all.mjs";' for name in names:
component_dir = f"toolkit/content/widgets/{name}"
with open(f"{component_dir}/{name}.mjs", "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(f"{component_dir}/{name}.css", "w", newline="\n") as f:
f.write(LICENSE_HEADER)
test_name = name.replace("-", "_")
test_path = f"toolkit/content/tests/widgets/test_{test_name}.html"
jar_path = "toolkit/content/jar.mn"
jar_lines = None with open(jar_path) as f:
jar_lines = f.readlines()
elements_startswith = " content/global/elements/"
new_css_line = (
f"{elements_startswith}{name}.css (widgets/{name}/{name}.css)\n"
)
new_js_line = (
f"{elements_startswith}{name}.mjs (widgets/{name}/{name}.mjs)\n"
)
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 andnot 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))
# Run prettier to fix the formatting generated by adding a new # entry to the Acorn elements array
run_mach(
command_context, "lint", argv=["--fix", "toolkit/content/customElements.js"]
)
story_path = f"{component_dir}/{name}.stories.mjs"
element_path = f"./{name}.mjs" 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,
story_prefix=story_prefix,
fixme_comment="",
element_path=element_path,
html_lit_import=html_lit_import,
)
)
@Command( "addstory",
category="misc",
description="Scaffold a front-end Storybook story.",
)
@CommandArgument( "name",
help="Story to create in kebab-case, eg. my-card.",
)
@CommandArgument( "project_name",
type=str,
help='Name of the project or team for the new component to keep stories organized. Eg. "Credential Management"',
)
@CommandArgument( "--path",
help="Path to the widget source, eg. /browser/components/my-module.mjs or chrome://browser/content/my-module.mjs",
) def addstory(command_context, name, project_name, path):
html_lit_import = 'import { html } from "lit.all.mjs";'
story_path = f"browser/components/storybook/stories/{name}.stories.mjs"
project_name = project_name.split()
project_name = " ".join(p.capitalize() for p in project_name)
story_prefix = f"Domain-specific UI Widgets/{project_name}" with open(story_path, "w", newline="\n") as f:
print(f"Creating new story {name} in {story_path}")
story_name = " ".join(p.capitalize() for p in name.split("-"))
f.write(
STORY_HEADER.format(
license=LICENSE_HEADER,
element_name=name,
story_name=story_name,
element_path=path,
fixme_comment=""if path else FIXME_COMMENT,
project_name=project_name,
story_prefix=story_prefix,
html_lit_import=html_lit_import,
)
)
@Command( "buildtokens",
category="misc",
description="Build the design tokens CSS files",
)
@CommandArgument( "--fetch-figma",
action="store_true",
help="Fetch the current Nova design tokens from Figma before building. " "Requires a valid FIGMA_ACCESS_TOKEN in your environment.",
) def buildtokens(command_context, fetch_figma): if run_mach(
command_context, "npm",
args=["ls", "--prefix=toolkit/themes/shared/design-system"],
):
run_mach(
command_context, "npm",
args=["ci", "--prefix=toolkit/themes/shared/design-system"],
) if fetch_figma:
failed = run_mach(
command_context, "npm",
args=[ "run", "fetch-figma-nova", "--prefix=toolkit/themes/shared/design-system",
],
) if failed: raise UserError( "Failed to access Figma API, is FIGMA_ACCESS_TOKEN set and valid?"
)
run_mach(
command_context, "npm",
args=[ "run", "build-figma-nova", "--prefix=toolkit/themes/shared/design-system",
],
)
run_mach(
command_context, "npm",
args=["run", "build", "--prefix=toolkit/themes/shared/design-system"],
)
run_mach(command_context, "newtab", subcommand="install")
run_mach(command_context, "newtab", subcommand="bundle")
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.