Merge branch 'master' of git.fsfe.org:FSFE/fsfe-website
This commit is contained in:
@@ -123,3 +123,24 @@ def get_basepath(file: Path) -> Path:
|
||||
def get_basename(file: Path) -> str:
|
||||
"""Return the name of the file with the last two suffixes removed."""
|
||||
return file.with_suffix("").with_suffix("").name
|
||||
|
||||
|
||||
def get_localised_file(base_file: Path, lang: str, suffix: str) -> Path | None:
|
||||
"""Return basefile localised if exists, else fallback if exists, else none."""
|
||||
# ensure the suffix has a leading .
|
||||
normalised_suffix = "." + suffix.removeprefix(".")
|
||||
return (
|
||||
localised
|
||||
if (
|
||||
localised := base_file.with_suffix(
|
||||
base_file.suffix + f".{lang}" + normalised_suffix
|
||||
)
|
||||
).exists()
|
||||
else fallback
|
||||
if (
|
||||
fallback := base_file.with_suffix(
|
||||
base_file.suffix + ".en" + normalised_suffix
|
||||
)
|
||||
).exists()
|
||||
else None
|
||||
)
|
||||
|
||||
@@ -14,7 +14,11 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from fsfe_website_build.lib.misc import get_basepath, sort_dict, update_if_changed
|
||||
from fsfe_website_build.lib.misc import (
|
||||
get_basepath,
|
||||
get_localised_file,
|
||||
update_if_changed,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import multiprocessing.pool
|
||||
@@ -24,62 +28,45 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
def _write_localmenus(
|
||||
source_dir: Path,
|
||||
directory: str,
|
||||
files_by_dir: dict[str, list[Path]],
|
||||
directory: Path,
|
||||
files: list[Path],
|
||||
languages: list[str],
|
||||
) -> None:
|
||||
"""Write localmenus for a given directory."""
|
||||
# Set of files with no langcode or xhtml extension
|
||||
base_files = {get_basepath(filter_file) for filter_file in files_by_dir[directory]}
|
||||
base_files = {get_basepath(file) for file in files}
|
||||
for lang in languages:
|
||||
file = Path(directory).joinpath(f".localmenu.{lang}.xml")
|
||||
logger.debug("Creating %s", file)
|
||||
localmenu_file = directory.joinpath(f".localmenu.{lang}.xml")
|
||||
logger.debug("Creating %s", localmenu_file)
|
||||
page = etree.Element("feed")
|
||||
|
||||
# Add the subelements
|
||||
version = etree.SubElement(page, "version")
|
||||
version.text = "1"
|
||||
etree.SubElement(page, "version").text = "1"
|
||||
|
||||
for source_file in [
|
||||
path
|
||||
for path in (
|
||||
base_file.with_suffix(f".{lang}.xhtml")
|
||||
if base_file.with_suffix(f".{lang}.xhtml").exists()
|
||||
else (
|
||||
base_file.with_suffix(".en.xhtml")
|
||||
if base_file.with_suffix(".en.xhtml").exists()
|
||||
else None
|
||||
)
|
||||
for base_file in base_files
|
||||
)
|
||||
if path is not None
|
||||
]:
|
||||
for base_file in base_files:
|
||||
# source file to get localmenu data from
|
||||
source_file = get_localised_file(base_file, lang, ".xhtml")
|
||||
if source_file is None:
|
||||
logger.debug("No source for basefile %s", base_file)
|
||||
continue
|
||||
# the file we are linking to in the localmenu
|
||||
link_file = base_file.with_suffix(base_file.suffix + ".html")
|
||||
# now generate a localmenu entry for each localmenu entry in the source file
|
||||
for localmenu in etree.parse(source_file).xpath("//localmenu"):
|
||||
etree.SubElement(
|
||||
page,
|
||||
"localmenuitem",
|
||||
set=(
|
||||
str(localmenu.xpath("./@set")[0])
|
||||
if localmenu.xpath("./@set") != []
|
||||
else "default"
|
||||
),
|
||||
id=(
|
||||
str(localmenu.xpath("./@id")[0])
|
||||
if localmenu.xpath("./@id") != []
|
||||
else "default"
|
||||
),
|
||||
set=localmenu.get("set", "default"),
|
||||
id=localmenu.get("id", "default"),
|
||||
link=(
|
||||
"/"
|
||||
+ str(
|
||||
source_file.with_suffix(".html").relative_to(source_dir),
|
||||
link_file.relative_to(source_dir),
|
||||
)
|
||||
),
|
||||
).text = localmenu.text
|
||||
|
||||
update_if_changed(
|
||||
file,
|
||||
etree.tostring(page, encoding="utf-8").decode("utf-8"),
|
||||
)
|
||||
update_if_changed(localmenu_file, etree.tostring(page, encoding="unicode"))
|
||||
|
||||
|
||||
def update_localmenus(
|
||||
@@ -91,44 +78,38 @@ def update_localmenus(
|
||||
"""Update all the .localmenu.*.xml files containing the local menus."""
|
||||
logger.info("Updating local menus")
|
||||
# Get a dict of all source files containing local menus
|
||||
files_by_dir: dict[str, set[Path]] = defaultdict(set)
|
||||
for file in filter(
|
||||
lambda path: "-template" not in path.name,
|
||||
source_dir.glob("**/*.??.xhtml"),
|
||||
files_by_dir: dict[Path, list[Path]] = defaultdict(list)
|
||||
for file in (
|
||||
file
|
||||
for file in source_dir.glob("**/*.??.xhtml")
|
||||
if "-template" not in file.name
|
||||
):
|
||||
xslt_root = etree.parse(file)
|
||||
if xslt_root.xpath("//localmenu"):
|
||||
directory_xpath = xslt_root.xpath("//localmenu/@dir")
|
||||
directory = str(
|
||||
source.joinpath(directory_xpath[0])
|
||||
if directory_xpath
|
||||
else file.parent.resolve().relative_to(source.resolve())
|
||||
for localmenu_elem in xslt_root.xpath("//localmenu"):
|
||||
directory = Path(
|
||||
localmenu_elem.get(
|
||||
"dir", str(file.parent.resolve().relative_to(source.resolve()))
|
||||
)
|
||||
)
|
||||
files_by_dir[directory].add(file)
|
||||
files_by_dir = sort_dict(files_by_dir)
|
||||
files_by_dir[directory].append(file)
|
||||
|
||||
# If any of the source files has been updated, rebuild all .localmenu.*.xml
|
||||
dirs = filter(
|
||||
lambda directory: (
|
||||
any(
|
||||
dirs = [
|
||||
(directory, files)
|
||||
for directory, files in files_by_dir.items()
|
||||
if any(
|
||||
[
|
||||
(
|
||||
(
|
||||
(not Path(directory).joinpath(".localmenu.en.xml").exists())
|
||||
or (
|
||||
file.stat().st_mtime
|
||||
> Path(directory)
|
||||
.joinpath(".localmenu.en.xml")
|
||||
.stat()
|
||||
.st_mtime
|
||||
)
|
||||
)
|
||||
for file in files_by_dir[directory]
|
||||
),
|
||||
)
|
||||
),
|
||||
files_by_dir,
|
||||
)
|
||||
not (
|
||||
localmenu_path := directory.joinpath(".localmenu.en.xml")
|
||||
).exists()
|
||||
)
|
||||
or (file.stat().st_mtime > localmenu_path.stat().st_mtime)
|
||||
]
|
||||
for file in files
|
||||
)
|
||||
]
|
||||
pool.starmap(
|
||||
_write_localmenus,
|
||||
((source_dir, directory, files_by_dir, languages) for directory in dirs),
|
||||
((source_dir, directory, files, languages) for directory, files in dirs),
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ from fsfe_website_build.lib.misc import (
|
||||
delete_file,
|
||||
get_basename,
|
||||
get_basepath,
|
||||
get_localised_file,
|
||||
get_version,
|
||||
keys_exists,
|
||||
lang_from_filename,
|
||||
@@ -111,3 +112,68 @@ def get_basepath_test() -> None:
|
||||
def get_basename_test() -> None:
|
||||
assert get_basename(Path("a.b.c")) == "a"
|
||||
assert get_basename(Path("a/b.c.d")) == "b"
|
||||
|
||||
|
||||
def get_localised_file_localized__test(tmp_path: Path) -> None:
|
||||
base_file = tmp_path / "test"
|
||||
base_file.write_text("content")
|
||||
|
||||
localized_file = tmp_path / "test.fr.xhtml"
|
||||
localized_file.write_text("french content")
|
||||
|
||||
result = get_localised_file(base_file, "fr", "xhtml")
|
||||
assert result == localized_file
|
||||
assert result is not None
|
||||
assert result.exists()
|
||||
|
||||
|
||||
def get_localised_file_localized_missing_test(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
base_file = tmp_path / "test"
|
||||
base_file.write_text("content")
|
||||
|
||||
fallback_file = tmp_path / "test.en.xhtml"
|
||||
fallback_file.write_text("english content")
|
||||
|
||||
result = get_localised_file(base_file, "de", "xhtml")
|
||||
assert result == fallback_file
|
||||
assert result is not None
|
||||
assert result.exists()
|
||||
|
||||
|
||||
def get_localised_file_neither_exists_test(tmp_path: Path) -> None:
|
||||
base_file = tmp_path / "test"
|
||||
base_file.write_text("content")
|
||||
|
||||
result = get_localised_file(base_file, "fr", "xhtml")
|
||||
assert result is None
|
||||
|
||||
|
||||
def get_localised_file_existing_suffix_test(tmp_path: Path) -> None:
|
||||
base_file = tmp_path / "test.suffix.test"
|
||||
base_file.write_text("content")
|
||||
|
||||
localized_file = tmp_path / "test.suffix.test.fr.xml"
|
||||
localized_file.write_text("xml content")
|
||||
|
||||
result = get_localised_file(base_file, "fr", "xml")
|
||||
assert result == localized_file
|
||||
assert result is not None
|
||||
assert result.exists()
|
||||
|
||||
|
||||
def get_localised_file_suffix_normalization_test(tmp_path: Path) -> None:
|
||||
base_file = tmp_path / "test"
|
||||
base_file.write_text("content")
|
||||
|
||||
localized_file = tmp_path / "test.fr.xml"
|
||||
localized_file.write_text("xml content")
|
||||
|
||||
result = get_localised_file(base_file, "fr", "xml")
|
||||
assert result == localized_file
|
||||
assert result is not None
|
||||
assert result.exists()
|
||||
|
||||
result2 = get_localised_file(base_file, "fr", ".xml")
|
||||
assert result2 == localized_file
|
||||
|
||||
@@ -24,6 +24,7 @@ RewriteRule ^graphics/fsfeurope.ico /graphics/fsfe.ico [R=301,L]
|
||||
# Redirect
|
||||
RewriteRule ^translate/?$ /contribute/translators/ [R=301,L]
|
||||
RewriteRule ^apple/?$ /activities/apple-litigation/ [R=301,L]
|
||||
RewriteRule ^at(ccc|CCC)/?$ /news/2025/news-20251214-01.html [R=302,L]
|
||||
|
||||
# Promotion material order
|
||||
RewriteRule ^promo(/.*)? /contribute/spreadtheword$1 [R=301,L]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<script src="/scripts/filter-teams.js"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="ltr">
|
||||
<p id="category"><a href="/about/">About</a></p>
|
||||
<h1>The FSFE Team</h1>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
</head>
|
||||
|
||||
<body class="spreadtheword">
|
||||
<body class="spreadtheword ltr">
|
||||
<p id="category"><a href="/contribute/">Contribute</a></p>
|
||||
|
||||
<h1 id="spread-the-word">Spread the word!</h1>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Events</title>
|
||||
</head>
|
||||
|
||||
<body class="toplevel article">
|
||||
<body class="toplevel article ltr">
|
||||
<h1>Events</h1>
|
||||
|
||||
<section id="add-event">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Announce your FSFE community event</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="ltr">
|
||||
<h1>Announce your FSFE community event</h1>
|
||||
|
||||
<div id="introduction">
|
||||
|
||||
@@ -1278,3 +1278,7 @@ blockquote#statement p {
|
||||
.special {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
118
fsfe.org/news/2025/news-20251214-01.en.xhtml
Normal file
118
fsfe.org/news/2025/news-20251214-01.en.xhtml
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<html newsdate="2025-12-16">
|
||||
<version>1</version>
|
||||
|
||||
<head>
|
||||
<title>Wrapping Up the Year With Free Software at the 39C3</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Wrapping Up the Year With Free Software at the 39C3</h1>
|
||||
|
||||
<p>Once again, the FSFE is heading to the Chaos Communication Congress!
|
||||
From 27 until the 30 December, we will be back in Hamburg as part of the
|
||||
Bits & Bäume assembly. Over 12.000 people will join us to
|
||||
participate in this community event, full of great talks, workshops and
|
||||
creatures from all over the world. Swing by, say hi, and warm up with
|
||||
some Free Software vibes!</p>
|
||||
|
||||
<figure>
|
||||
<img src="https://pics.fsfe.org/uploads/medium/d7/aa/cb70feb82ed93d9abfc1a6709cd3.jpeg"
|
||||
alt="38c3 at Hamburg Messe in 2024: The building at night full of lights "/>
|
||||
</figure>
|
||||
|
||||
|
||||
<p>As the Christmas markets wind down, the Hamburg Congress Center
|
||||
begins to transform. People arrive from all directions; spaceships and
|
||||
blinking lights appear; hackerspaces from across Europe start setting up
|
||||
their assemblies. Civil society groups gather to showcase their work and
|
||||
their hopes for the future, while art installations rise piece by piece.
|
||||
A low murmur fills the CCH, one that is growing louder and more vibrant
|
||||
by the minute: an unmistakable sign that the Chaos Communication
|
||||
Congress is coming back to life.</p>
|
||||
|
||||
<p>The 39th edition of this well-known event will once again take over
|
||||
Hamburg from December 27 to 30, filling the post-Christmas lull with
|
||||
creativity, tech, activism, and a whole lot of interesting people. This
|
||||
conference, organised by and for the community, brings together around
|
||||
12,000 participants each year, people who do not want to miss the chance
|
||||
to be part of this utopic and ever-evolving event full of community,
|
||||
curiosity, and digital freedom. For four days, the CCH becomes a
|
||||
temporary city: a place where bold ideas are built overnight and where
|
||||
the boundaries of technology, art, and society are constantly being
|
||||
pushed and reimagined.</p>
|
||||
|
||||
<p>You will find the FSFE crew <a
|
||||
href="https://events.ccc.de/congress/2025/hub/en/assembly/detail/bitsundbaeume_aboutfreedom">at
|
||||
the Bits & Bäume assembly</a> with a
|
||||
booth with stickers and merchandise, as well as a full program
|
||||
presenting our 2048 vision: a future in which everyone has the right to
|
||||
remove and install any software on any of their devices, all public
|
||||
funding for software is dedicated exclusively to Free Software,
|
||||
regulatory frameworks actively encourage the use and development of Free
|
||||
Software, licensing and legal decisions are grounded in facts rather
|
||||
than fear, uncertainty, and doubt, and young people can tinker,
|
||||
experiment, and learn to code with Free Software as the default. Come
|
||||
by, meet us, and help us turn this vision into reality.</p>
|
||||
<p>Of course, we will not be alone: plenty of other Bits & Bäume
|
||||
organisations will be right around us, bringing brilliant talks, fun
|
||||
workshops, and lively booths. And do not forget the hackerspaces and the
|
||||
official program! With so many exciting things happening around the
|
||||
clock for four full days, the real challenge will be choosing where to
|
||||
go next.</p>
|
||||
|
||||
<p>So, <a href="/events/index.html#event-20251227-01">what to expect
|
||||
from the FSFE at 39C3?</a> We are planning to have a
|
||||
dedicated FSFE contributors and volunteers meeting, <a
|
||||
href="http://ada.fsfe.org/">“Ada & Zangemann”</a> reading, hands-on
|
||||
workshops about
|
||||
<a href="http://reuse.software">REUSE</a> and about running an
|
||||
organisation with Free Software, a deep dive
|
||||
into <a href="/activities/deviceneutrality/index.html">Device
|
||||
Neutrality</a> and the <a
|
||||
href="/activities/apple-litigation/apple-litigation.html">Apple v. EU
|
||||
litigation</a>, and of course we
|
||||
will be answering your questions about our Vision 2048 and current
|
||||
activities such as <a href="http://yh4f.org/">Youth Hacking 4 Freedom</a>, which is open for
|
||||
registration and will start directly after the 39C3 is over.</p>
|
||||
|
||||
<p>But, most importantly bring your instruments and yourself to our
|
||||
booth for our daily 19:00h Free Software sing-along. So, stop by, warm
|
||||
up, say hello, and share some Free Software holiday cheer with us. </p>
|
||||
<p>
|
||||
We are looking forward to seeing you at <a
|
||||
href="https://events.ccc.de/congress/2025/infos/startpage.html">39C3!</a>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
||||
<tags>
|
||||
<tag key="news">News</tag>
|
||||
<tag key="front-page"/>
|
||||
<tag key="reuse">REUSE</tag>
|
||||
<tag key="policy">Policy</tag>
|
||||
<tag key="pmpc">Public Money? Public Code!</tag>
|
||||
<tag key="dma">DMA</tag>
|
||||
<tag key="ccc">Chaos Communication Congress</tag>
|
||||
<tag key="ngi">Next Generation Internet</tag>
|
||||
<tag key="ada-zangemann">Ada and Zangemann</tag>
|
||||
<tag key="fediverse">Fediverse</tag>
|
||||
<tag key="deviceneutrality">Device Neutrality</tag>
|
||||
<tag key="legal">Legal</tag>
|
||||
<tag key="merchandise">Merchandise</tag>
|
||||
<tag key="community">Community</tag>
|
||||
<tag key="de">Germany</tag>
|
||||
<tag key="fya">Free Your Android</tag>
|
||||
<tag key="yh4f">Youth Hacking 4 Freedom</tag>
|
||||
<tag key="windows-tax">Windows refund</tag>
|
||||
<tag key="highlights">Highlights</tag>
|
||||
|
||||
</tags>
|
||||
|
||||
<discussion href="https://mastodon.social/deck/@fsfe/115729419639756759"/>
|
||||
|
||||
<image url="https://pics.fsfe.org/uploads/medium/d7/aa/cb70feb82ed93d9abfc1a6709cd3.jpeg"
|
||||
alt="38c3 at Hamburg Messe in 2024: The building at night full of lights "/>
|
||||
</html>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>News</title>
|
||||
</head>
|
||||
|
||||
<body class="toplevel news-index">
|
||||
<body class="toplevel news-index ltr">
|
||||
<h1>News</h1>
|
||||
|
||||
<div id="introduction">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<title>Newsletters</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="ltr">
|
||||
<h1>Newsletters</h1>
|
||||
<p id="introduction">
|
||||
In addition to our <a href="news.html">regular news stories</a>, each
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Software Freedom Podcast</title>
|
||||
</head>
|
||||
|
||||
<body class="news-index">
|
||||
<body class="news-index ltr">
|
||||
<!-- Breadcumb -->
|
||||
<p id="category"><a href="news.html">News</a></p>
|
||||
<!-- / Breadcumb -->
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Merchandise</title>
|
||||
</head>
|
||||
|
||||
<body class="toplevel">
|
||||
<body class="toplevel ltr">
|
||||
<h1>Merchandise</h1>
|
||||
|
||||
<module id="order-delay"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-supporter">
|
||||
<div class="banner-become-supporter ltr">
|
||||
<p>
|
||||
Our intervention requires sustainable funding.
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-contributor">
|
||||
<div class="banner-become-contributor ltr">
|
||||
<p>
|
||||
Join us in our work for software freedom.
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-supporter">
|
||||
<div class="banner-become-supporter ltr">
|
||||
<p>
|
||||
Freedom in the information society needs your financial contribution.
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-translator">
|
||||
<div class="banner-become-translator ltr">
|
||||
<p>
|
||||
Help to spread the word about Free Software!
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-supporter">
|
||||
<div class="banner-become-supporter ltr">
|
||||
<p>
|
||||
Become an FSFE supporter and help us fight for Router Freedom in Europe!
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-subscribe-box">
|
||||
<div class="banner-subscribe-box ltr">
|
||||
<p>
|
||||
Subscribe to our email updates. Our experts inform you about current
|
||||
news, events, activities, and how you can contribute. <span style="font-size:0.8em">(Our <a href="/about/legal/imprint.html#id-privacy-policy"><span style="color:white; text-decoration: underline;">Privacy Policy</span></a>)</span>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>3</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-subscribe">
|
||||
<div class="banner-subscribe ltr">
|
||||
<p>
|
||||
Subscribe to our email updates. Our experts inform you about current
|
||||
news, events, activities, and how you can contribute. <span style="font-size:0.8em">(Our <a href="/about/legal/imprint.html#id-privacy-policy"><span style="color:white; text-decoration: underline;">Privacy Policy</span></a>)</span>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="banner-become-supporter">
|
||||
<div class="banner-become-supporter ltr">
|
||||
<p>
|
||||
Software Freedom needs your financial contribution.
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<div class="module-follow-news">
|
||||
<div class="module-follow-news ltr">
|
||||
<h2>Follow our News</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<p class="alert alert-success">
|
||||
<p class="alert alert-success ltr">
|
||||
<strong>SUMMER SALE!</strong> No shipping costs to all orders from 6 euros until 30 June!
|
||||
</p>
|
||||
</module>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>1</version>
|
||||
|
||||
<module>
|
||||
<p class="alert alert-danger">
|
||||
<p class="alert alert-danger ltr">
|
||||
At the moment we cannot process promotion material and merchandise orders
|
||||
at the usual speed. Anyway, our staffers are doing their best to satisfy
|
||||
all your requests as quickly as possible. Thank you for your understanding
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<version>2</version>
|
||||
|
||||
<module>
|
||||
<div class="module-social-media">
|
||||
<div class="module-social-media ltr">
|
||||
<h2>Social Media</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<data>
|
||||
<version>6</version>
|
||||
<div class="text-button-box">
|
||||
<div class="text-button-box" style="direction: ltr;">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 col-md-10">
|
||||
<p>
|
||||
|
||||
@@ -34,13 +34,10 @@ ENV PATH="$UV_PROJECT_ENVIRONMENT/bin:$PATH"
|
||||
# Set the workdir
|
||||
WORKDIR /website-source-during-build
|
||||
|
||||
# Copy the pyproject and build deps
|
||||
# Done in a seperate step for optimal docker caching
|
||||
COPY ./pyproject.toml ./uv.lock ./
|
||||
RUN uv sync --no-install-package fsfe_website_build --group dev
|
||||
# Copy pyproject, build deps & entrypoint
|
||||
COPY ./pyproject.toml ./uv.lock pre-commit.entrypoint.sh ./
|
||||
|
||||
# Copy entrypoint
|
||||
COPY pre-commit.entrypoint.sh ./
|
||||
RUN uv sync --no-install-package fsfe_website_build --group dev
|
||||
|
||||
# Set the workdir
|
||||
WORKDIR /website-source
|
||||
|
||||
Reference in New Issue
Block a user