diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..e8350138 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,58 @@ +# Code owners for pybcn/pybcn.github.io +# +# This site takes pull requests from outside contributors. A speaker edits +# their own page under content/people/, which is fine and stays unowned so +# that it needs no organizer. +# +# The paths below are different. A change there reaches every page of the +# site, or reaches money, or reaches the deploy. Each one needs a review +# from @pybcn/web. +# +# GitHub applies the last matching rule, and every rule here has the same +# owner, so the order does not change the outcome. +# +# @pybcn/web has push access on this repository and its visibility is +# "closed", which is what GitHub needs in order to send it a review request. +# A secret team is a valid owner on paper and silently receives nothing. + +# Deploy. The workflow runs on every push and holds the publish credentials. +/.github/ @pybcn/web + +# Build and release scripts. They run on a maintainer machine. +/bin/ @pybcn/web + +# Site configuration. It sets the markup safety flags, the base URL and the +# analytics identifier. +/config.toml @pybcn/web + +# Layouts and shortcodes. A change here renders on many pages at once. +# +# layouts/shortcodes/membership/membership-process.html holds the PayPal +# hosted_button_id of the association. One changed character in that value +# sends the membership fees to another PayPal account, and the page still +# looks correct. This is the strongest single reason this path is owned. +/layouts/ @pybcn/web + +# Static assets served from the site root, including files that browsers +# fetch with no further checking. +/static/ @pybcn/web + +# The theme: every template, partial, script and stylesheet of the site. +/themes/ @pybcn/web + +# Association pages: statutes, the code of conduct, membership and payment +# instructions. These carry legal and financial statements. +/content/pybcn_association/ @pybcn/web + +# The custom domain of the GitHub Pages site. A change to this file points +# pybcn.org somewhere else. +/CNAME @pybcn/web + +# Sponsors and events. A sponsor file carries a name, a logo file name and the +# tier it is listed under, and an event file decides which sponsors and which +# people a page shows. Both render on pages an outside contributor never +# touches, so a wrong value there is visible to everyone and obvious to +# nobody. These are the paths a hostile sponsor entry would come through. +/content/sponsors/ @pybcn/web +/content/events/ @pybcn/web + diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7d28d312..fadd92b9 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -43,6 +43,9 @@ jobs: - name: Check front matter and cross-references run: bin/check-content + - name: Check content for dangerous raw HTML + run: bin/check-html-safety + links: name: Check the links runs-on: ubuntu-latest diff --git a/README.md b/README.md index 268ead52..476d100c 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,40 @@ Once the site was archived, you can create a new link in the navigational menu u ## Information for developers +### Content safety check + +`bin/check-html-safety` scans `content/` and fails if it finds raw HTML that +turns a content change into script execution, a redirect, a credential prompt +or a page overlay: ` +) +BINARY_SUFFIXES = ( + ".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico", + ".pdf", +) + + +# Patterns that must not appear in content. +# +# The "on..." pattern carries a word boundary. An HTML event handler attribute +# starts at a boundary, and without the boundary the pattern also matches the +# middle of ordinary words in prose. +PATTERNS = [ + # A tag name must end at the match, or trips
and + # trips . \b is not enough: it allows . + ("script", re.compile(r"])", re.I), "inline or external script"), + ("style", re.compile(r"])", re.I), "inline stylesheet, can cover the page"), + ("iframe", re.compile(r"])", re.I), "embedded third party document"), + # srcdoc holds a whole document inline, and that document runs in the + # origin of the page that embeds it, so it is script execution on this + # site. The browser also prefers srcdoc over src, so a permitted src next + # to it means nothing. No LOAD_ATTRIBUTES entry exists for it, so no + # allowlist entry can clear it. + ("srcdoc", re.compile(r"(?])", re.I), "plugin object"), + ("embed", re.compile(r"])", re.I), "plugin embed"), + ("form", re.compile(r"])", re.I), "form that can post elsewhere"), + ("meta", re.compile(r"])", re.I), "meta tag, can refresh or redirect"), + ("link", re.compile(r"])", re.I), "link tag, can pull in a stylesheet"), + ("base", re.compile(r"])", re.I), "base tag, rewrites every relative URL"), + # An event handler is on=, so require a letter after "on" and reject + # an underscore, which made on_error= a false positive. + ("handler", re.compile(r"(? is not touched by Hugo's render hook, so javascript:, + javascript:, java script: and a scheme split across a newline all + reach the page working. html.unescape handles every HTML5 named entity, + including the case-sensitive ones such as and that a + hand-written table gets wrong. + + The offsets exist because the normalised text has no newlines, so a line + number counted in it is always the first line. Decoding an entity also + changes the length. Without the map, every scheme finding reported the + line the body starts on, whatever line it was really on. + """ + out, offsets = [], [] + index, end = 0, len(text) + while index < end: + entity = ENTITY.match(text, index) + if entity: + decoded = html.unescape(entity.group(0)) + if decoded != entity.group(0): + for char in decoded: + if not DROPPED.match(char): + out.append(char) + offsets.append(index) + index = entity.end() + continue + char = text[index] + if not DROPPED.match(char): + out.append(char) + offsets.append(index) + index += 1 + return "".join(out), offsets + + +def split_front_matter(text): + """Return (front matter text, body text, body start line). + + Front matter is the block between the first two "---" lines. A file with + no front matter gives ("", whole text, 1). + """ + if not text.startswith("---"): + return "", text, 1 + lines = text.split("\n") + for index in range(1, len(lines)): + if lines[index].rstrip() == "---": + return "\n".join(lines[1:index]), "\n".join(lines[index + 1:]), index + 2 + # Unterminated front matter. Treat the whole file as front matter. + return text, "", 1 + + +def walk_strings(node, path=""): + """Yield (location, string) for every string inside a parsed YAML value.""" + if isinstance(node, str): + yield path or "", node + elif isinstance(node, dict): + for key, value in node.items(): + if isinstance(key, str): + yield from walk_strings(key, "%s/" % path if path else "") + child = "%s.%s" % (path, key) if path else str(key) + yield from walk_strings(value, child) + elif isinstance(node, list): + for index, value in enumerate(node): + yield from walk_strings(value, "%s[%d]" % (path, index)) + + +def snippet(text, at, width=110): + """Return a one line excerpt of text around offset at.""" + start = max(0, at - 20) + piece = text[start:start + width].replace("\n", " ").replace("\t", " ") + return re.sub(r"\s{2,}", " ", piece).strip() + + +def line_of(text, at): + return text.count("\n", 0, at) + 1 + + +def match_region(text, at, limit=800): + """Return the text of the HTML tag or the value that starts at offset at. + + The region ends at the first ">" after the offset, because an attribute + value cannot hold a bare ">". A match with no closing ">" falls back to a + fixed window. + + The allowlist is matched against this region and not against the whole + file. Matching the whole file would let a second, hostile iframe ride + along in a file that already has an allowed one. + """ + end = text.find(">", at) + if end == -1 or end - at > limit: + end = min(len(text), at + limit) + else: + end += 1 + return text[at:end] + + +# The attribute a browser loads each element from, by pattern name. An +# allowlist entry is matched against these attributes and no other. The +# browser ignores data=, href= or title= on an iframe and loads src, so a +# permitted URL in any of those does not make the frame safe. +LOAD_ATTRIBUTES = { + "a": ("href",), + "embed": ("src",), + "form": ("action",), + "iframe": ("src", "srcdoc"), + "img": ("src", "srcset"), + "link": ("href",), + "object": ("data",), + "script": ("src",), +} + +# One attribute and its value. The lookbehind stops data-src= from matching +# as src=. The value is double quoted, single quoted or bare. +ATTRIBUTE_VALUE = r"""(?]+))""" + + +def benign_style(text, at): + """True when the style attribute that starts at offset at passes SAFE_STYLE.""" + match = re.compile(ATTRIBUTE_VALUE % "style", re.I).match(text, at) + if not match: + return False + value = next(g for g in match.groups() if g is not None) + return bool(SAFE_STYLE.match(value)) + + +def load_urls(pattern_name, region): + """Return the URLs that the element named by pattern_name loads. + + Only the first occurrence of an attribute counts. The HTML parser drops a + repeated attribute, so

Sponsors

+{{< google-embed kind="calendar" height="600" + title="Agenda of PyDay BCN 2019" + src="https://calendar.google.com/calendar/embed?height=600&wkst=1&bgcolor=%23ffffff&ctz=Europe%2FMadrid&mode=AGENDA&showNav=0&showDate=0&showTabs=0&showCalendars=0&showTz=1&src=eTEway53c19pdWMxYW00c2Y5c3V2NGtqcjV0YXZuYzEzY0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t&color=%23F09300&title=Agenda%20del%20evento&showTitle=0" >}} +

Sponsors

Venue

diff --git a/content/events/pyday_bcn/pyday_bcn_2020.md b/content/events/pyday_bcn/pyday_bcn_2020.md index a7dc3698..75f2a627 100644 --- a/content/events/pyday_bcn/pyday_bcn_2020.md +++ b/content/events/pyday_bcn/pyday_bcn_2020.md @@ -95,7 +95,7 @@ events: language: "English" speaker: "Ankit Mahato" type: talk - python_level: Beginner + python_level: beginner topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 16:45 @@ -108,7 +108,7 @@ events: language: "Spanish" speaker: "Daniel Mesejo" type: talk - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 17:15 @@ -121,7 +121,7 @@ events: language: "Catalan" speaker: "Ferran Fábregas" type: lightning - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 17:30 @@ -134,7 +134,7 @@ events: language: "English" speaker: "Julio Martínez" type: lightning - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 17:45 @@ -147,7 +147,7 @@ events: language: "English" speaker: "Miroslav Šedivý" type: lightning - python_level: Intermediate + python_level: intermediate topic: Python programming location: YouTube track1 - start_time_slot: 18:00 @@ -160,7 +160,7 @@ events: language: "Catalan" speaker: "Carles Barrobés" type: lightning - python_level: Intermediate + python_level: intermediate topic: Python programming location: YouTube track1 @@ -174,7 +174,7 @@ events: language: "Spanish" speaker: "Elisabeth Ortega Carrasco" type: talk - python_level: Beginner + python_level: beginner topic: IOT location: YouTube track2 - start_time_slot: 16:45 @@ -187,7 +187,7 @@ events: language: "English" speaker: "Christian Adell" type: talk - python_level: Intermediate + python_level: intermediate topic: Network automation location: YouTube track2 - start_time_slot: 17:15 @@ -200,7 +200,7 @@ events: language: "English" speaker: "Christian Adell" type: lightning - python_level: Beginner + python_level: beginner topic: Python programming location: YouTube track2 - start_time_slot: 17:30 @@ -213,7 +213,7 @@ events: language: "English" speaker: "Alvaro Duran" type: lightning - python_level: Beginner + python_level: beginner topic: Python programming location: YouTube track2 - start_time_slot: 17:45 @@ -226,7 +226,7 @@ events: location: YouTube track2 topic: Web development, microservices language: "English" - python_level: Intermediate + python_level: intermediate speaker: Francesco Faraone - start_time_slot: 18:15 @@ -246,7 +246,7 @@ events: language: "English" speaker: "Eduard Cespedes Borras" type: talk - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 19:00 @@ -259,7 +259,7 @@ events: language: "English" speaker: "Alberto Camara" type: talk - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 19:30 @@ -272,7 +272,7 @@ events: language: "English" speaker: "Edgar Riba" type: talk - python_level: Intermediate + python_level: intermediate topic: Data Science, ML, DL location: YouTube track1 - start_time_slot: 20:00 @@ -285,7 +285,7 @@ events: language: "English" speaker: "Joan Fontanals Martinez" type: talk - python_level: Beginner + python_level: beginner topic: Data Science, ML, DL location: YouTube track1 @@ -299,7 +299,7 @@ events: language: "English" speaker: "Marc Pous" type: talk - python_level: Beginner + python_level: beginner topic: IOT location: YouTube track2 - start_time_slot: 19:00 @@ -312,7 +312,7 @@ events: language: "English" speaker: "Jose Haro Peralta" type: talk - python_level: Beginner + python_level: beginner topic: Web location: YouTube track2 - start_time_slot: 19:30 @@ -325,7 +325,7 @@ events: language: "English" speaker: "Maria Teresa Grifa" type: talk - python_level: Beginner + python_level: beginner topic: Python programming location: YouTube track2 - start_time_slot: 20:00 @@ -338,7 +338,7 @@ events: language: "English" speaker: "Gajendra Deshpande" type: talk - python_level: Beginner + python_level: beginner topic: Security location: YouTube track2 @@ -367,4 +367,4 @@ PyDay BCN 2020 will have different **thematic tracks** --e.g. data science, web ### Sponsor us! -Would you like to sponsor PyDay BCN 2020? Have a look at the sponsorship brochure!

+Would you like to sponsor PyDay BCN 2020? Have a look at the [sponsorship brochure](https://bit.ly/pydaybcn-2020-sponsoring)! diff --git a/content/events/pyday_bcn/pyday_bcn_2021.md b/content/events/pyday_bcn/pyday_bcn_2021.md index 6f68e862..a5c2f83a 100644 --- a/content/events/pyday_bcn/pyday_bcn_2021.md +++ b/content/events/pyday_bcn/pyday_bcn_2021.md @@ -87,7 +87,15 @@ previous_editions: spansDuration: 15 numTracks: 4 eventTimes: [9:00, 9:15, 9:30, 9:45, 10:00, 10:15, 10:30, 10:45, 11:00, 11:15, 11:30, 11:45, 12:00, 12:15, 12:30, 12:45, 13:00, 13:15, 13:30, 13:45, 14:00, 14:15, 14:30, 14:45, 15:00, 15:15, 15:30, 15:45, 16:00, 16:15, 16:30, 16:45, 17:00, 17:15, 17:30, 17:45] -legend: " Workshop     Talk    |    Beginner     Intermediate     Advanced    |    Sponsored event" +legend: + - type: workshop + - type: talk + - separator: true + - level: beginner + - level: intermediate + - level: advanced + - separator: true + - type: sponsor events: - start_time_slot: 9:00 end_time_slot: 9:15 @@ -109,8 +117,8 @@ events: language: "Spanish" type: workshop topic: Data Apps - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Actes - speaker: "Diego Gonzalez" sponsor: Preply @@ -123,8 +131,8 @@ events: language: "English" type: workshop topic: Web development - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate location: Room Guinardó - speaker: "Esperanza Buitrago" title: "Implementing your API with FASTAPI" @@ -136,8 +144,8 @@ events: language: "English" type: workshop topic: Software Engineering - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner location: Room Gòtica requirements: "
  • Python3
  • Visual Studio Code
  • Pip3
  • Conda
  • We'll do everything from scratch: such as installing FastAPI, uvicorn and typing
" @@ -152,8 +160,8 @@ events: language: "English" type: workshop topic: Cloud-native Python applications - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Raval requirements: "Python 3.8+" @@ -178,8 +186,8 @@ events: language: "Spanish" type: workshop topic: User interfaces - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Actes - speaker: "Gabriel de Maeztu" sponsor: IOMED @@ -192,8 +200,8 @@ events: language: "English" type: workshop topic: Data Science - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate location: Room Guinardó - speaker: "Vincent Choubard" sponsor: Rover @@ -206,8 +214,8 @@ events: language: "English" type: workshop topic: Web Development - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner location: Room Gòtica requirements: "Ideally have python and django installed on your machine by following https://docs.djangoproject.com/en/3.2/intro/install/" - speaker: "Antonio Molina, Erik Tordera, Pablo Fernández" @@ -221,8 +229,8 @@ events: language: "Spanish" type: workshop topic: Architecture - python_level: "" - topic_level: "" + python_level: beginner + topic_level: intermediate location: Room Raval - start_time_slot: 13:00 @@ -253,8 +261,8 @@ events: language: "Spanish" type: workshop topic: Data science - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate location: Room Actes requirements: "A browser (preferably Google Chrome)
Github account." - speaker: "Jordi Mur" @@ -268,8 +276,8 @@ events: language: "English" type: workshop topic: Data science - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Guinardó - speaker: "Matteo Bruno" sponsor: Onna @@ -326,8 +334,8 @@ events: language: "English" type: workshop topic: IOT, ML, Edge AI - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Actes - speaker: "Mariana Meireles, Laysa Uchoa" title: "The moons of Jupyter: widgets ecosystem" @@ -339,8 +347,8 @@ events: language: "English" type: workshop topic: Data science, scientific computing - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Guinardó requirements: "https://github.com/jupyter-widgets/tutorial#readme

But a link to a Binder project where you can run the workshop without installing anything on your machine will also be provided. It’s recommendable to install requirements locally, though." - speaker: "Vivek Sharma" @@ -353,8 +361,8 @@ events: language: "English" type: workshop topic: Signal Processing - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner location: Room Gòtica - speaker: "Christian Adell" title: "Keeping sync between datasets with Diffsync" @@ -367,8 +375,8 @@ events: language: "English" type: workshop topic: Data set synchronisation - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner location: Room Raval - start_time_slot: 17:30 @@ -388,11 +396,11 @@ events: We are organizing the **the fifth edition** of PyDay in Barcelona! -PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the last four editions, PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! +PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the [last four editions](#previous_editions_section), PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! #### When and where -It is scheduled for **Saturday 27th November** in Canòdrom - Ateneu d'Innovació Digital i Democràtica, from 9:30pm to 19:00pm CET, aprox. +It is scheduled for **Saturday 27th November** in [Canòdrom - Ateneu d'Innovació Digital i Democràtica](https://g.page/Canodrom?share), from 9:30pm to 19:00pm CET, aprox. diff --git a/content/events/pyday_bcn/pyday_bcn_2022.md b/content/events/pyday_bcn/pyday_bcn_2022.md index 74dcaa62..65f9c317 100644 --- a/content/events/pyday_bcn/pyday_bcn_2022.md +++ b/content/events/pyday_bcn/pyday_bcn_2022.md @@ -124,7 +124,13 @@ eventTimes: 17:30, 17:45, ] -legend: ' Workshop     Talk    |    Beginner     Intermediate     Advanced' +legend: + - type: workshop + - type: talk + - separator: true + - level: beginner + - level: intermediate + - level: advanced events: - start_time_slot: 9:00 end_time_slot: 9:15 @@ -145,8 +151,8 @@ events: color: red type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "
  • Laptop , requirements.txt installed.
  • VS Code IDE.
" topic: "Data Science and MLOPS" location: Sala d'actes Ada Lovelace @@ -159,8 +165,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "
  • Initial python knowledges
  • Would be great to know Django
  • Laptop with installed Docker and Docker Compose
  • " topic: "Security, software development" location: Sala Hedy Lamarr / Margarita Salas @@ -173,8 +179,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Serverless apps" location: Sala Hipàtia d'Alexandria requirements: "Python, AWS account, AWS chalice framework" @@ -197,8 +203,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Laptop" topic: "Internet of Things and Air quality sensors" location: Sala d'actes Ada Lovelace @@ -211,8 +217,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "
    • Familiarity with Python and basic understanding of HTML and CSS (ideally JS too, but it is not necessary)
    • Laptop with Python3, Flask, NuxtJS and Docker.
    " topic: "Web apps" location: Sala Hedy Lamarr / Margarita Salas @@ -225,8 +231,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "Laptop with conda if attendees want to follow the notebooks and do some exercises, just ears and be present otherwise." topic: "Python as a GIS" location: Sala Hipàtia d'Alexandria @@ -258,8 +264,8 @@ events: color: yellow type: workshop language: "Spanish or English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: intermediate topic: "Data engineering" location: Sala d'actes Ada Lovelace requirements: "Follow the installation steps in https://github.com/alabarga/pybcn22-modern-data-stack" @@ -272,8 +278,8 @@ events: color: blue type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Scrapy" requirements: "Laptop" location: Sala Hedy Lamarr / Margarita Salas @@ -286,8 +292,8 @@ events: color: blue type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Laptop" topic: "Observability" location: Sala Hipàtia d'Alexandria @@ -337,8 +343,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "This workshop is for Data scientists or developers who have math-heavy code that would like to speed up with the benefit of Numpy and Numba.

    What is required from attendees

    • - A computer with a stable internet connection (useful to look up information);
    • - Python 3.8 or above;
    • - Jupyter and Numba installed (detail about Python libraries required will be announced later);
    • - An opened mind and ready to learn something new
    " topic: "Data Science" location: Sala d'actes Ada Lovelace @@ -351,8 +357,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner topic: "Data Management" location: Sala Hedy Lamarr / Margarita Salas requirements: "For the folks who would like to follow along, a laptop with docker compose" @@ -365,8 +371,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Test driven development " location: Sala Hipàtia d'Alexandria @@ -407,11 +413,11 @@ events: We are organizing the **the sixth edition** of PyDay in Barcelona! -PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the last five editions, PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! +PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the [last five editions](#previous_editions_section), PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! #### When and where -It is scheduled for **Saturday 26th November** in Canòdrom - Ateneu d'Innovació Digital i Democràtica, from 9:30pm to 19:00pm CET, aprox. +It is scheduled for **Saturday 26th November** in [Canòdrom - Ateneu d'Innovació Digital i Democràtica](https://g.page/Canodrom?share), from 9:30pm to 19:00pm CET, aprox. #### A full day of in-person hands-on workshops diff --git a/content/events/pyday_bcn/pyday_bcn_2023.md b/content/events/pyday_bcn/pyday_bcn_2023.md index 18efa9a1..3d260811 100644 --- a/content/events/pyday_bcn/pyday_bcn_2023.md +++ b/content/events/pyday_bcn/pyday_bcn_2023.md @@ -127,7 +127,13 @@ eventTimes: 17:30, 17:45, ] -legend: ' Workshop     Talk    |    Beginner     Intermediate     Advanced' +legend: + - type: workshop + - type: talk + - separator: true + - level: beginner + - level: intermediate + - level: advanced events: - start_time_slot: 9:00 end_time_slot: 9:15 @@ -148,8 +154,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Python, PyTorch, Jupyter, Matplotlib." topic: "Data science" location: Room B6 @@ -167,8 +173,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "To have the `qibo` package installed." topic: "Quantum Computing" location: Room B5 @@ -181,8 +187,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: intermediate topic: "Network/Infrastructure Automation" location: Room B3 requirements: "" @@ -205,8 +211,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "" topic: "Data Science" location: Room B6 @@ -219,8 +225,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "Numpy, Scipy, Matplotlib, PyTorch, Qiskit" topic: "Quantum Computing" location: Room B5 @@ -234,8 +240,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Laptop with latest Python version available and git installed" topic: "Python Packaging" location: Room B3 @@ -267,8 +273,8 @@ events: color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "" topic: "Data science" location: Room B6 @@ -281,8 +287,8 @@ events: color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate topic: "API requests" requirements: "Python 3.8 or above, VSCode or some similar IDE, FastApi and uvicorn libraries" location: Room B5 @@ -295,8 +301,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "" topic: "Documentation and blogging" location: Room B3 @@ -342,8 +348,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: advanced requirements: "Python, Docker" topic: "Data Science" location: Room B6 @@ -357,8 +363,8 @@ events: color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "" topic: "General, Core" location: Room B5 @@ -372,8 +378,8 @@ events: color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requeriments: "Python with pytest installed, code editor, git (for downloading the exercise)." topic: "Test driven development" location: Room B3 @@ -419,11 +425,11 @@ events: We are organizing the **the seventh edition** of PyDay in Barcelona! -PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the last six editions, PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! +PyDay is an event full of FREE **python-related workshops** and activities for the Python community, organized once per year. Over the [last six editions](#previous_editions_section), PyDay has become a great opportunity to share our love for Python and engage users, companies and newcomers into it! #### When and where -It is scheduled for **Saturday 11th November** in Universitat de Barcelona, from 9:00am to 18:00pm CET, aprox. +It is scheduled for **Saturday 11th November** in [Universitat de Barcelona](https://maps.app.goo.gl/RT9THKhxqz3eTvxf7), from 9:00am to 18:00pm CET, aprox. #### A full day of in-person hands-on workshops diff --git a/content/events/pyday_bcn/pyday_bcn_2024.md b/content/events/pyday_bcn/pyday_bcn_2024.md index cc902f4c..c09b00a0 100644 --- a/content/events/pyday_bcn/pyday_bcn_2024.md +++ b/content/events/pyday_bcn/pyday_bcn_2024.md @@ -124,7 +124,13 @@ eventTimes: 17:30, 17:45, ] -legend: ' Workshop     Talk    |        Intermediate     Advanced' +legend: + - type: workshop + - type: talk + - separator: true + - level: beginner + - level: intermediate + - level: advanced events: - start_time_slot: 9:00 end_time_slot: 9:15 @@ -144,8 +150,8 @@ events: color: red type: workshop language: English - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "numpy, scikit-learn, and keras installed" topic: "Data science, ML" location: "Sala d'actes Ada Lovelace" @@ -186,8 +192,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Testing" location: "Sala Margarita Salas" requirements: "A Github account" @@ -242,8 +248,8 @@ During the talk, my idea is to present the tool and the technological solutions color: red type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "torch==2.0.1 torchvision==0.15.2 matplotlib==3.7.1" topic: "Artificial Intelligence" location: "Sala d'actes Ada Lovelace" @@ -258,8 +264,8 @@ During the talk, my idea is to present the tool and the technological solutions color: green type: workshop language: "Català" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "https://github.com/OriolAbril/pyday2024-xarray/blob/main/requirements.txt" topic: "Data science" location: "Aula Hipàtia d'Alexandria" @@ -280,8 +286,8 @@ During the talk, my idea is to present the tool and the technological solutions color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: intermediate requirements: "https://github.com/alexmolas/python-static-typing/blob/main/requirements.txt" topic: "Programming" location: "Aula Hedy Lamarr" @@ -294,8 +300,8 @@ During the talk, my idea is to present the tool and the technological solutions color: blue type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: intermediate requirements: "Git, Docker Desktop, Visual Studio Code" topic: "Data engineering" location: "Sala Margarita Salas" @@ -348,8 +354,8 @@ During the talk, my idea is to present the tool and the technological solutions color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: advanced + topic_level: advanced topic: "Serverless development" location: "Sala d'actes Ada Lovelace" requirements: "AWS Account" @@ -376,8 +382,8 @@ During the talk, my idea is to present the tool and the technological solutions color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate topic: "Apache Arrow, Data Science" requirements: "You will be able to find both the requirements and the Notebooks on the following repository: https://github.com/raulcd/2024-pyday-bcn-arrow-workshop" location: "Sala Margarita Salas" @@ -420,8 +426,8 @@ During the talk, my idea is to present the tool and the technological solutions color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Data engineering" location: "Sala d'actes Ada Lovelace" requirements: "Docker, Conda" @@ -434,8 +440,8 @@ During the talk, my idea is to present the tool and the technological solutions color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Postgres and MySQL installed locally or via Docker" topic: "Databases" location: "Aula Hipàtia d'Alexandria" @@ -450,8 +456,8 @@ During the talk, my idea is to present the tool and the technological solutions color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner topic: "Web development, Videogames" location: "Aula Hedy Lamarr" - speaker: "Asia Noble" @@ -467,8 +473,8 @@ During the talk, my idea is to present the tool and the technological solutions color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner topic: "Data science" location: "Sala Margarita Salas" requirements: "Data Science techstack: PowerBI, Python, Scikit Learn, Tensorflow. Background n the creative tech industry, management, consulting, and operations." @@ -518,11 +524,11 @@ The project involved developing three separate GNN models, one for each protein, We are excited to announce the **8th edition** of PyDay in Barcelona! -PyDay is an event packed with FREE **python-related workshops** and activities for the Python community. It is organized once per year. Over the last seven editions, PyDay has become a fantastic opportunity to share our love for Python and engage users, companies, and newcomers! +PyDay is an event packed with FREE **python-related workshops** and activities for the Python community. It is organized once per year. Over the [last seven editions](#previous_editions_section), PyDay has become a fantastic opportunity to share our love for Python and engage users, companies, and newcomers! #### When and where -It is scheduled for **Saturday 9th November** at Canòdrom, from 9:00 a.m. to 18:00 p.m. CET, approximately. +It is scheduled for **Saturday 9th November** at [Canòdrom](https://maps.app.goo.gl/Uxiao2Dr7uio9o3v9), from 9:00 a.m. to 18:00 p.m. CET, approximately. #### A full day of in-person, hands-on workshops diff --git a/content/events/pyday_bcn/pyday_bcn_2025.md b/content/events/pyday_bcn/pyday_bcn_2025.md index c7b60d84..31d2c2bf 100644 --- a/content/events/pyday_bcn/pyday_bcn_2025.md +++ b/content/events/pyday_bcn/pyday_bcn_2025.md @@ -153,7 +153,13 @@ eventTimes: 17:30, 17:45, ] -legend: ' Workshop     Talk    |    Beginner     Intermediate     Advanced' +legend: + - type: workshop + - type: talk + - separator: true + - level: beginner + - level: intermediate + - level: advanced events: - start_time_slot: 9:00 end_time_slot: 9:15 @@ -174,8 +180,8 @@ events: color: blue type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Intermediate experience in Python and basic understanding of LLMs and how to use LLM APIs" topic: "LLM" location: "Sala d'actes Ada Lovelace" @@ -190,8 +196,8 @@ events: color: yellow type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: " - No prior experience with AI or machine learning - Basic familiarity with Python (variables, functions, running scripts) @@ -213,8 +219,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "pip install qilisdk" topic: "Quantum Computing" location: "Sala Hedy Lamarr" @@ -231,8 +237,8 @@ events: color: orange type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate requirements: "Python environment y IDE" topic: "Testing" location: "Sala Hipàtia d'Alexandria" @@ -256,8 +262,8 @@ events: color: blue type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Conexión a internet, cuenta de Google (para trabajar en Google Colab a través de librerías ya disponibles sin necesidad de usar consola de comandos (cmd) ni instalar Python en local." topic: "Data science, Natural Language Process, Data Visualization" location: "Sala d'actes Ada Lovelace" @@ -283,8 +289,8 @@ events: color: yellow type: workshop language: "Spanish/English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Conexión a internet. Python 3.10+. Tener la librería \"openai\" instalada. No se necesitará una API key para el taller. Se recomienda usar un gestor de entornos como uv o virtualenv, aunque no es obligatorio. Cada participante debe tener su entorno listo. Durante el taller se utilizará \"uv\" para gestionar dependencias." topic: "LLM" location: "Sala Margarita Salas" @@ -299,8 +305,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate topic: "Data Science" location: "Sala Hedy Lamarr" requirements: "Participants should bring a laptop with: @@ -325,8 +331,8 @@ events: color: orange type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "Python and DOCX" topic: "Artificial Intelligence" location: "Sala Hipàtia d'Alexandria" @@ -371,8 +377,8 @@ events: color: blue type: workshop language: "Spanish/English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Python 3.10+ (cada participante puede decidir seguir el taller con un Jupyter Notebook, Google Colab, scripts de Python, etc). El taller se desarrollará utilizando archivos de texto de Python, pero es apto para seguirlo en un notebook también." topic: "LLM" location: "Sala d'actes Ada Lovelace" @@ -400,8 +406,8 @@ events: color: yellow type: workshop language: "Catalan" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: intermediate topic: "Computer vision" requirements: "Python" location: "Sala Margarita Salas" @@ -422,8 +428,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: advanced + topic_level: advanced requirements: "python, transformers, llama-index" topic: "Agent IA" location: "Sala Hedy Lamarr" @@ -438,8 +444,8 @@ events: color: orange type: workshop language: "Catalan" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Utilitzarem la última versió de la llibreria bambi durant el taller. Es recomana tenir un virtual environment amb la llibreria ja instal·lada si es vol seguir el taller en directe. El taller també assumeix un nivell intermedi en l'ús de NumPy i Pandas." topic: "Statistics and Data Science" location: "Sala Hipàtia d'Alexandria" @@ -463,8 +469,8 @@ events: color: blue type: workshop language: "Spanish" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Portátil y acceso a internet, para poder clonar el repositorio y seguir las instrucciones." topic: "IA Generativa" location: "Sala d'actes Ada Lovelace" @@ -483,8 +489,8 @@ events: color: yellow type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: beginner + topic_level: beginner requirements: "" topic: "" location: "Sala Margarita Salas" @@ -499,8 +505,8 @@ events: color: red type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner topic: "Web development" location: "Sala Hedy Lamarr" repositories: "https://github.com/ericmassip/carbon-home-watcher" @@ -514,8 +520,8 @@ events: color: orange type: workshop language: "English" - python_level: "" - topic_level: "" + python_level: intermediate + topic_level: beginner requirements: "Notebook and basic python knowledge" topic: "Causal Inference & Data Science" location: "Sala Hipàtia d'Alexandria" @@ -546,11 +552,11 @@ events: We are excited to announce the **9th edition** of PyDay in Barcelona! -PyDay is an event packed with FREE **Python-related workshops** and activities for the Python community. It is organized once per year. Over the last eight editions, PyDay has become a fantastic opportunity to share our love for Python and engage users, companies, and newcomers! +PyDay is an event packed with FREE **Python-related workshops** and activities for the Python community. It is organized once per year. Over the [last eight editions](#previous_editions_section), PyDay has become a fantastic opportunity to share our love for Python and engage users, companies, and newcomers! #### When and where -It is scheduled for **Saturday 29th November** at Canòdrom, from 9:00 a.m. to 18:00 p.m. CET, approximately. +It is scheduled for **Saturday 29th November** at [Canòdrom](https://maps.app.goo.gl/Uxiao2Dr7uio9o3v9), from 9:00 a.m. to 18:00 p.m. CET, approximately. #### A full day of in-person, hands-on workshops diff --git a/content/people/alex-molas.md b/content/people/alex-molas.md index e51bf27f..4e1f5d9a 100644 --- a/content/people/alex-molas.md +++ b/content/people/alex-molas.md @@ -9,8 +9,8 @@ twitter: https://x.com/molasalex linkedin: https://www.linkedin.com/in/alex-molas --- -I’m a husband, father, physicist, and data scientist. In that order. -
    Husband: I met my soulmate when we were 13, we started dating when we were 18, and we got married when we were 24. -
    Father: we became parents in 2020, and then again in 2022. And it’s the best thing that has ever happened to us. -
    Physicist: I studied a degree and a master in physics. I even published a paper in Nature. -
    Data Scientist: after studying physics I realized that academia wasn’t for me. For the past seven years, I’ve been learning, building, and breaking things related to data. Now, I work as a Data Scientist at Wallapop where I build machine learning systems to help you find the best items. \ No newline at end of file +I’m a husband, father, physicist, and data scientist. In that order.\ +Husband: I met my soulmate when we were 13, we started dating when we were 18, and we got married when we were 24.\ +Father: we became parents in 2020, and then again in 2022. And it’s the best thing that has ever happened to us.\ +Physicist: I studied a degree and a master in physics. I even published a paper in Nature.\ +Data Scientist: after studying physics I realized that academia wasn’t for me. For the past seven years, I’ve been learning, building, and breaking things related to data. Now, I work as a Data Scientist at Wallapop where I build machine learning systems to help you find the best items. \ No newline at end of file diff --git a/content/people/ferran-fabregas.md b/content/people/ferran-fabregas.md index f59f0574..830230d5 100644 --- a/content/people/ferran-fabregas.md +++ b/content/people/ferran-fabregas.md @@ -11,4 +11,6 @@ github: https://github.com/ferrithemaker site: https://ferranfabregas.me/ --- -Within this time I have published the book “How to use Raspberry Pi 4 through 100 practical exercises“ from Marcombo publisher and I’m working on another book about electronics for Makers. I have also been responsible for the technical correction of the Spanish translation of some tech-related books of the O’Reilly and Willey publishers.

    I have presented different personal projects at fairs in London, Avignon and Brussels MakersTown, also at some Maker Faires held in Spain (Madrid, León, Bilbao and Barcelona), Maker Faire European Edition Rome’19, and at the MIT MediaLab in Cambridge, Massachusetts, in addition to publishing articles in magazines such as MagPi and the book “The official Raspberry Pi projects book”. +Within this time I have published the book “How to use Raspberry Pi 4 through 100 practical exercises“ from Marcombo publisher and I’m working on another book about electronics for Makers. I have also been responsible for the technical correction of the Spanish translation of some tech-related books of the O’Reilly and Willey publishers. + +I have presented different personal projects at fairs in London, Avignon and Brussels MakersTown, also at some Maker Faires held in Spain (Madrid, León, Bilbao and Barcelona), Maker Faire European Edition Rome’19, and at the MIT MediaLab in Cambridge, Massachusetts, in addition to publishing articles in magazines such as MagPi and the book “The official Raspberry Pi projects book”. diff --git a/content/pybcn_association/coc.md b/content/pybcn_association/coc.md index 64d316fe..c44d1a02 100644 --- a/content/pybcn_association/coc.md +++ b/content/pybcn_association/coc.md @@ -40,6 +40,5 @@ organizers/representatives of any physical events put on under the auspices of PyBCN. This Code of Conduct has been adapted from the -PyLadies one and is licensed under a -Creative Commons Attribution-Share Alike 3.0 Unported -license. +[PyLadies](https://www.pyladies.com/CodeOfConduct/) one and is licensed under a +[Creative Commons Attribution-Share Alike 3.0 Unported license](https://creativecommons.org/licenses/by-sa/3.0/). diff --git a/content/pybcn_association/information.md b/content/pybcn_association/information.md index c4e9c256..ff9ca5e2 100644 --- a/content/pybcn_association/information.md +++ b/content/pybcn_association/information.md @@ -30,17 +30,17 @@ We have a Management Board and a Permanent Committee to make decisions, and work * Secretary: Daniel Mesejo Leon * Treasurer: Yago Tafalla * Board member of Comunication: Mauricio Volcanes - * Board member of Events: Sergi Ramírez Mitjans

    + * Board member of Events: Sergi Ramírez Mitjans * **Permanent Committee**: It is mostly a consultive board and help coordinate the work groups. -* **Work groups** to drive all the association activity: +* [**Work groups**](https://docs.google.com/spreadsheets/d/1ptmymYA5R4vJ4H38Fm7mo_yMooZI39sdLD9DRXxyfaE) to drive all the association activity: * **Meetup**: This work group organizes, prepares, coordinates and runs the PyBCN meetups every month. * **PyLadies**: They have been running the monthly PyLadies BCN workshops and activities. * **Practice Sessions**: This work group have been running the monthly PyBCN workshops and dojos. * **Communication**: They handle our communication channels, publishing of content, and collaboration with sponsors. * **Web**: This work group cares about our web page and its publishing process. - * **Video**: This work group is responsible for the recording of the talks in our meetups and activities and the publishing in our Youtube channel. + * **Video**: This work group is responsible for the recording of the talks in our meetups and activities and the publishing in our [Youtube channel](https://www.youtube.com/channel/UCEhI2CfdT5--TYq47K4en4A). * **Other work groups**: Some work groups are formed to run a specific event, like the PyDays. All the work groups must follow some rules: @@ -52,18 +52,18 @@ All the work groups must follow some rules: * There's no other requirement to be a member of any work group. ## Association documentation -* PyBCN Association Statutes -* Internal Regulations +* [PyBCN Association Statutes](https://docs.google.com/document/d/1F0VzZPrBsTtBl-U7PkA6IerFHnLqjTDspUaNQfu1vCU/edit?usp=sharing) +* [Internal Regulations](https://docs.google.com/document/d/1xd36jkdcT3s3zGjNrSMnGuuk5xgodAos2fLDyJMLE30/edit?usp=sharing) * [Code of Conduct](/pybcn_association/coc/) -* Founding Act -* Assamblea General Ordinària 2019 -* Assamblea General Ordinària 2020 -* Assamblea General Ordinària 2021 -* Assamblea General Ordinària 2022 -* Assamblea General Ordinària 2023 -* Assamblea General Ordinària 2024 -* Assamblea Extraordinària 2025 -* Assamblea General Ordinària 2026 +* [Founding Act](https://docs.google.com/document/d/1_fTbgT-Bw25aaGLb9O9vCMi1Gkxhb3FiY-S7yeZLq6k/edit?usp=sharing) +* [Assamblea General Ordinària 2019](https://docs.google.com/document/d/1mJuuoymGJe4ayO5y08yN0bHBSqrPPyRZW2QLQSXXuYg/edit?usp=sharing) +* [Assamblea General Ordinària 2020](https://docs.google.com/document/d/1yLR9p_vDKZPs0NlVMaKtrBMooqHdDyY0Lk5cPmcGs5I/edit?usp=sharing) +* [Assamblea General Ordinària 2021](https://docs.google.com/document/d/1Qi0efxdC7T2bk2oVT2z6tTrrJ3UONwCK3Vnf3cL4KFA/edit?usp=sharing) +* [Assamblea General Ordinària 2022](https://docs.google.com/document/d/13xiLuUGIzT8kyZWGTkA6T-dbUO7Y_Z6hlUjakkwlSGM/edit?usp=sharing) +* [Assamblea General Ordinària 2023](https://docs.google.com/document/d/1CnJzGjz7COsc-45w5tEVu5gpDBv1mUozFh4eGXw8-GU/edit?usp=sharing) +* [Assamblea General Ordinària 2024](https://docs.google.com/document/d/1IDYEQvStyM8YxQHIcmZbfE0SYePDGDavHssz3CG3d1E/edit?usp=share_link) +* [Assamblea Extraordinària 2025](https://docs.google.com/document/d/12BHpSCe7yOdgdm7JiuzKxT_RNKyxHN18R9p0_1rCWl4/edit?usp=share_link) +* [Assamblea General Ordinària 2026](https://docs.google.com/document/d/1Yx_4OMf3TkUDrI4MT3FD4NWm0y-3mSh32krX5F1RqMY/edit?usp=sharing) ## Past Management Boards * Management Board 2018 - 2025 diff --git a/content/pybcn_association/membership-cancel.md b/content/pybcn_association/membership-cancel.md index fe9e2f7d..abc5905e 100644 --- a/content/pybcn_association/membership-cancel.md +++ b/content/pybcn_association/membership-cancel.md @@ -11,25 +11,15 @@ _build: --- -
    -
    -
    - {{% membership/membership-must-and-can %}} -
    -
    -

    -

    -

    - {{% membership/membership-process %}} -

    You can find more information about the association here -

    If you have any doubt, please don't hesitate to contact us.

    -
    -
    -
    - - - - - +{{< grid-row >}} +{{< grid-col md="6" >}} +{{< membership/membership-must-and-can >}} +{{< /grid-col >}} +{{< grid-col md="6" >}} +{{< alert type="danger" >}} +The payment process has been canceled. +{{< /alert >}} +{{< membership/membership-process >}} +{{< membership/membership-links >}} +{{< /grid-col >}} +{{< /grid-row >}} diff --git a/content/pybcn_association/membership-thanks.md b/content/pybcn_association/membership-thanks.md index 6388a605..44f93edb 100644 --- a/content/pybcn_association/membership-thanks.md +++ b/content/pybcn_association/membership-thanks.md @@ -11,25 +11,15 @@ _build: --- -
    -
    -
    - {{% membership/membership-must-and-can %}} -
    -
    -

    -

    -

    -

    If you haven't already, please remember to fill the PyBCN Membership Form.

    -

    You can find more information about the association here -

    If you have any doubt, please don't hesitate to contact us.

    -
    -
    -
    - - - - - +{{< grid-row >}} +{{< grid-col md="6" >}} +{{< membership/membership-must-and-can >}} +{{< /grid-col >}} +{{< grid-col md="6" >}} +{{< alert type="success" >}} +We'll contact you shortly by email with you membership number and a big thank you :D +{{< /alert >}} +{{< membership/membership-form-reminder >}} +{{< membership/membership-links >}} +{{< /grid-col >}} +{{< /grid-row >}} diff --git a/content/pybcn_association/membership.md b/content/pybcn_association/membership.md index 4a59969b..41677f19 100644 --- a/content/pybcn_association/membership.md +++ b/content/pybcn_association/membership.md @@ -13,20 +13,12 @@ heroBackground: /images/photos/people-pydata-2017.jpg The Python Barcelona Association, a.k.a. PyBCN, is a non-profit organisation with more than 10 years of history, focused on increasing the usage and knowledge of the Python programming language. By becoming a member, you'll support the association's activities and programs, helping us to increase the number of activities, to improve them (i.e. getting a better recording system for the meetups) and to cover basic expenses (domains, meetup fees...). **For just 20€/year you can now become a member of our community!** -
    -
    -
    - {{% membership/membership-must-and-can %}} -
    -
    - {{% membership/membership-process %}} -

    You can find more information about the association here -

    If you have any doubt, please don't hesitate to contact us.

    -
    -
    -
    - - - - - +{{< grid-row >}} +{{< grid-col md="6" >}} +{{< membership/membership-must-and-can >}} +{{< /grid-col >}} +{{< grid-col md="6" >}} +{{< membership/membership-process >}} +{{< membership/membership-links >}} +{{< /grid-col >}} +{{< /grid-row >}} diff --git a/content/pybcn_association/propose-a-talk.md b/content/pybcn_association/propose-a-talk.md index e430553d..ee578b9d 100644 --- a/content/pybcn_association/propose-a-talk.md +++ b/content/pybcn_association/propose-a-talk.md @@ -8,4 +8,6 @@ weight: 4 heroBackground: /images/photos/propose-a-talk.jpg --- - +{{< google-embed kind="form" height="550" + title="Propose a talk for a PyBCN meetup" + src="https://docs.google.com/forms/d/13mlS704es_BkALALScL6wmROhyDqdag74ShPYo1yt2A/viewform" >}} diff --git a/content/pyladies_bcn/_index.md b/content/pyladies_bcn/_index.md index 73957063..60f5cb68 100644 --- a/content/pyladies_bcn/_index.md +++ b/content/pyladies_bcn/_index.md @@ -8,21 +8,31 @@ layout: "contact" heroBackground: /images/photos/pyladies/header/header3.jpeg config: "pyladies_first" --- -
    -
    -

    Meet PyLadiesBCN

    -

    About PyLadiesBCN!
    Learn all about our mission

    -

    Organisers and speakers!
    The people that make it possible

    -

    Upcoming meetups!
    Discover our next events

    -

    Talk and teach!
    Give a talk or guide a practice session

    -
    -
    -
    -
    -

    Are you a company?

    -

    Sponsor a PyLadiesBCN event!
    Help us to organize our next event

    -

    Share your job offers!
    Reach our >600 mailing list subscribers

    -

    Organize a Python-related event!
    We can help

    -

    Contact us!
    How can we help?

    -
    -
    + +{{< bordered-col icon="fa-users" title="Meet PyLadiesBCN" >}} +**[About PyLadiesBCN!](/pyladies_bcn/about)**\ +Learn all about our mission + +**[Organisers and speakers!](/pyladies_bcn/organizers-and-speakers)**\ +The people that make it possible + +**[Upcoming meetups!](/pyladies_bcn/meetups)**\ +Discover our next events + +**[Talk and teach!](/pyladies_bcn/call-for-proposals)**\ +Give a talk or guide a practice session +{{< /bordered-col >}} + +{{< bordered-col icon="fa-briefcase" title="Are you a company?" >}} +**[Sponsor a PyLadiesBCN event!](/pyladies_bcn/sponsors)**\ +Help us to organize our next event + +**[Share your job offers!](/pyladies_bcn/job-offers)**\ +Reach our >600 mailing list subscribers + +**[Organize a Python-related event!](/pybcn_association/promote-your-event)**\ +We can help + +**[Contact us!](/pyladies_bcn/contact-us)**\ +How can we help? +{{< /bordered-col >}} diff --git a/content/pyladies_bcn/about.md b/content/pyladies_bcn/about.md index d6627277..e18d1cb9 100644 --- a/content/pyladies_bcn/about.md +++ b/content/pyladies_bcn/about.md @@ -36,6 +36,6 @@ We are an **international mentorship group** with a focus on providing a friendl Would you like to participate? Have a look at our [upcoming events!](/pyladies_bcn/meetups/) Would you like to collaborate? [Contact us!](/pyladies_bcn/contact-us/) -And if you'd like to get some more information about our parent organisation, check out their website. +And if you'd like to get some more information about our parent organisation, check out [their website](http://www.pyladies.com). All our events adhere to a strong [Code of Conduct](/pybcn_association/coc/). diff --git a/content/pyladies_bcn/call-for-proposals.md b/content/pyladies_bcn/call-for-proposals.md index 05692e3e..d6b75ca9 100644 --- a/content/pyladies_bcn/call-for-proposals.md +++ b/content/pyladies_bcn/call-for-proposals.md @@ -8,4 +8,6 @@ weight: 4 heroBackground: /images/photos/propose-a-talk.jpg --- - +{{< google-embed kind="form" height="550" + title="PyLadies BCN call for proposals" + src="https://docs.google.com/forms/d/e/1FAIpQLSfEnxT7IrbsFvVbofwcFVqO_uKy9n74STbnfC_zCP_prvJIKA/viewform" >}} diff --git a/content/pyladies_bcn/contact-us.md b/content/pyladies_bcn/contact-us.md index 5584747c..e2f9df41 100644 --- a/content/pyladies_bcn/contact-us.md +++ b/content/pyladies_bcn/contact-us.md @@ -10,19 +10,24 @@ heroBackground: https://images.unsplash.com/photo-1512626120412-faf41adb4874?ixl config: "pyladies_first" --- -
    -
    -

    Are you a company?

    -

    Sponsor a PyLadiesBCN event!
    Help us to organize our next event

    -

    Share your job offers!
    Reach our >600 mailing list subscribers

    -

    Organize a Python-related event!
    We can help

    -
    -
    -
    -
    -

    Are you a Python fan?

    -

    Talk and teach!
    Give a talk or guide a practice session

    -

    Organize with us!
    Help us to organize our next event

    -

    Become a PyBCN member!
    It's cool, and it's only 20€ per year

    -
    -
    +{{< bordered-col icon="fa-briefcase" title="Are you a company?" >}} +**[Sponsor a PyLadiesBCN event!](/pybcn_association/sponsor-us)**\ +Help us to organize our next event + +**[Share your job offers!](/pyladies_bcn/job-offers)**\ +Reach our >600 mailing list subscribers + +**[Organize a Python-related event!](/pybcn_association/promote-your-event)**\ +We can help +{{< /bordered-col >}} + +{{< bordered-col icon="fa-users" title="Are you a Python fan?" >}} +**[Talk and teach!](/pyladies_bcn/call-for-proposals)**\ +Give a talk or guide a practice session + +**[Organize with us!](/pybcn_association/organize-with-us)**\ +Help us to organize our next event + +**[Become a PyBCN member!](/pybcn_association/membership)**\ +It's cool, and it's only 20€ per year +{{< /bordered-col >}} diff --git a/layouts/_default/_markup/render-link.html b/layouts/_default/_markup/render-link.html new file mode 100644 index 00000000..a6070c00 --- /dev/null +++ b/layouts/_default/_markup/render-link.html @@ -0,0 +1,23 @@ +{{- /* + Link render hook. + + Content used to write raw to open an + external site in a new tab. With goldmark unsafe off, raw HTML in content + no longer renders, so a plain markdown link has to carry that behaviour. + + An external link gets target="_blank" and rel="noopener noreferrer". + The rel part is new: target="_blank" on its own hands the opened page a + window.opener handle to this one, which is a reverse tabnabbing path. + + A relative link, an anchor, a mailto: link and a link back to this site + keep the default behaviour and open in the same tab. +*/ -}} +{{- $url := urls.Parse .Destination -}} +{{- $external := and $url.Host (ne $url.Host (urls.Parse .Page.Site.BaseURL).Host) -}} +{{- /* + The attributes are written by the template, not assembled with printf and + emitted through safeHTMLAttr. Go's %q is shell-style quoting, not HTML + escaping: a quote in a link title came back as \" , which closes the + attribute early and leaves the rest of the title as stray attribute names. +*/ -}} +{{ .Text }} \ No newline at end of file diff --git a/layouts/shortcodes/alert.html b/layouts/shortcodes/alert.html new file mode 100644 index 00000000..ce31ce2f --- /dev/null +++ b/layouts/shortcodes/alert.html @@ -0,0 +1,16 @@ +{{- /* + alert: a Bootstrap alert box. + + Usage: {{< alert type="success" >}}Your message{{< /alert >}} + + The type is checked against the Bootstrap set, so content cannot put an + arbitrary class here. role="alert" tells a screen reader to announce it. +*/ -}} +{{- $type := or (.Get "type") "info" -}} +{{- $allowed := slice "primary" "secondary" "success" "danger" "warning" "info" "light" "dark" -}} +{{- if not (in $allowed $type) -}} + {{- errorf "alert: type %q is not one of %s (%s)" $type (delimit $allowed ", ") .Position -}} +{{- end -}} + diff --git a/layouts/shortcodes/bordered-col.html b/layouts/shortcodes/bordered-col.html new file mode 100644 index 00000000..f452fb98 --- /dev/null +++ b/layouts/shortcodes/bordered-col.html @@ -0,0 +1,29 @@ +{{- /* + bordered-col: one bordered card in a column, with an icon heading. + + Usage: + {{< bordered-col icon="fa-briefcase" title="For companies!" >}} + **[Become a PyBCN sponsor](/pybcn_association/sponsor-us)**\ + Help us to organize our next event + {{< /bordered-col >}} + + The body is markdown. Keep it to markdown only: text, links, emphasis and + a backslash at the end of a line for a line break. A shortcode that emits + HTML cannot be nested here, because markdownify runs with goldmark unsafe + off and drops the tags. + + Set chevrons="true" to put a chevron before each link, which the contact + page does. The chevron comes from CSS, not from the content. +*/ -}} +{{- $md := or (.Get "md") "4" -}} +{{- if not (findRE `^(1[0-2]|[1-9])$` $md) -}} + {{- errorf "bordered-col: md must be 1 to 12, got %q (%s)" $md .Position -}} +{{- end -}} +
    +
    + {{- with .Get "title" }} +

    {{ with $.Get "icon" }} {{ end }}{{ . }}

    + {{- end }} + {{ .Inner | markdownify }} +
    +
    diff --git a/layouts/shortcodes/google-embed.html b/layouts/shortcodes/google-embed.html new file mode 100644 index 00000000..68e5b5ae --- /dev/null +++ b/layouts/shortcodes/google-embed.html @@ -0,0 +1,38 @@ +{{- /* + google-embed: embed a Google Form or a Google Calendar. + + Usage: + {{< google-embed kind="form" src="https://docs.google.com/forms/d/.../viewform" >}} + {{< google-embed kind="calendar" src="https://calendar.google.com/calendar/embed?..." title="Agenda" >}} + + An iframe is the one piece of third party markup this site needs, because + PyBCN has no form backend of its own. The shortcode keeps it out of + content: the host is checked against the table below, so content can name + a Google Form or a Google Calendar and nothing else. + + The iframe carries a title, which a screen reader needs to say what the + frame holds, and which the raw HTML in content did not have. +*/ -}} +{{- $kinds := dict + "form" (dict "host" "docs.google.com" "prefix" "https://docs.google.com/forms/" "title" "Google Form") + "calendar" (dict "host" "calendar.google.com" "prefix" "https://calendar.google.com/calendar/embed" "title" "Google Calendar") +-}} +{{- $kind := .Get "kind" -}} +{{- $spec := index $kinds $kind -}} +{{- if not $spec -}} + {{- errorf "google-embed: kind must be form or calendar, got %q (%s)" $kind .Position -}} +{{- end -}} +{{- $src := .Get "src" -}} +{{- if not (hasPrefix $src $spec.prefix) -}} + {{- errorf "google-embed: src must start with %q, got %q (%s)" $spec.prefix $src .Position -}} +{{- end -}} +{{- $height := or (.Get "height") "550" -}} +{{- if not (findRE `^[0-9]{2,4}$` $height) -}} + {{- errorf "google-embed: height must be a number, got %q (%s)" $height .Position -}} +{{- end -}} + diff --git a/layouts/shortcodes/grid-col.html b/layouts/shortcodes/grid-col.html new file mode 100644 index 00000000..36591e4f --- /dev/null +++ b/layouts/shortcodes/grid-col.html @@ -0,0 +1,15 @@ +{{- /* + grid-col: a Bootstrap column inside grid-row. + + Usage: {{< grid-col md="6" >}}...{{< /grid-col >}} + + The body is not markdown, it is other shortcodes. markdownify cannot be + used here: it runs goldmark with unsafe off, which would drop the HTML + that a nested shortcode produces. Wrap prose in a shortcode that + markdownifies its own body, such as prose or alert. +*/ -}} +{{- $md := or (.Get "md") "6" -}} +{{- if not (findRE `^(1[0-2]|[1-9])$` $md) -}} + {{- errorf "grid-col: md must be 1 to 12, got %q (%s)" $md .Position -}} +{{- end -}} +
    {{ .Inner }}
    diff --git a/layouts/shortcodes/grid-row.html b/layouts/shortcodes/grid-row.html new file mode 100644 index 00000000..f0891ff5 --- /dev/null +++ b/layouts/shortcodes/grid-row.html @@ -0,0 +1,16 @@ +{{- /* + grid-row: a Bootstrap row. + + Usage: + {{< grid-row >}} + {{< grid-col md="6" >}}...{{< /grid-col >}} + {{< grid-col md="6" >}}...{{< /grid-col >}} + {{< /grid-row >}} + + The body is not markdown. Put only grid-col shortcodes in it. + + The single.html layout already wraps page content in + container > row > col, so a row here nests inside that column, which is + the correct Bootstrap way to subdivide a column. +*/ -}} +
    {{ .Inner }}
    diff --git a/layouts/shortcodes/icon.html b/layouts/shortcodes/icon.html new file mode 100644 index 00000000..11e8635e --- /dev/null +++ b/layouts/shortcodes/icon.html @@ -0,0 +1,19 @@ +{{- /* + icon: a Font Awesome icon. + + Usage: {{< icon "fa-briefcase" >}} + {{< icon name="fa-star" style="fas" >}} + + The name is checked against a pattern before it goes into the class + attribute, so content cannot put anything else there. The icon is + decorative, so it is hidden from screen readers. +*/ -}} +{{- $name := or (.Get "name") (.Get 0) -}} +{{- $style := or (.Get "style") "fas" -}} +{{- if not (in (slice "fas" "far" "fab" "fa") $style) -}} + {{- errorf "icon: style %q is not one of fas, far, fab, fa (%s)" $style .Position -}} +{{- end -}} +{{- if not (findRE `^fa-[a-z0-9-]+$` $name) -}} + {{- errorf "icon: name %q must look like fa-example (%s)" $name .Position -}} +{{- end -}} + \ No newline at end of file diff --git a/layouts/shortcodes/logo-row.html b/layouts/shortcodes/logo-row.html new file mode 100644 index 00000000..624a440c --- /dev/null +++ b/layouts/shortcodes/logo-row.html @@ -0,0 +1,12 @@ +{{- /* + logo-row: a centred row of sponsor logos. + + Usage: + {{< logo-row >}} + {{< logo src="/archives/.../kiwicom.png" alt="Kiwi.com" height="150" >}} + {{< /logo-row >}} + + Replaces the
    element and the inline style attributes that the + archived event pages carried.
    has been obsolete since HTML 4. +*/ -}} +
    {{ .Inner }}
    diff --git a/layouts/shortcodes/logo.html b/layouts/shortcodes/logo.html new file mode 100644 index 00000000..280e6c06 --- /dev/null +++ b/layouts/shortcodes/logo.html @@ -0,0 +1,27 @@ +{{- /* + logo: one sponsor logo inside logo-row. + + Usage: {{< logo src="/path/logo.png" alt="Company" height="150" >}} + {{< logo src="/path/logo.png" alt="Company" width="350" >}} + + alt is required. The archived pages had elements with no alt text at + all, so a screen reader read out the file name or nothing. + + width and height are plain numbers of pixels, checked before they reach + the style attribute. +*/ -}} +{{- $src := .Get "src" -}} +{{- $alt := .Get "alt" -}} +{{- if not $src -}}{{ errorf "logo: src is required (%s)" .Position }}{{- end -}} +{{- if not $alt -}}{{ errorf "logo: alt is required, name the sponsor (%s)" .Position }}{{- end -}} +{{- $size := slice -}} +{{- with .Get "width" -}} + {{- if not (findRE `^[0-9]{1,4}$` .) -}}{{ errorf "logo: width must be a number of pixels, got %q (%s)" . $.Position }}{{- end -}} + {{- $size = $size | append (printf "width:%spx" .) -}} +{{- end -}} +{{- with .Get "height" -}} + {{- if not (findRE `^[0-9]{1,4}$` .) -}}{{ errorf "logo: height must be a number of pixels, got %q (%s)" . $.Position }}{{- end -}} + {{- $size = $size | append (printf "height:%spx" .) -}} +{{- end -}} +{{ $alt }} diff --git a/layouts/shortcodes/membership/membership-form-reminder.html b/layouts/shortcodes/membership/membership-form-reminder.html new file mode 100644 index 00000000..a3f06fea --- /dev/null +++ b/layouts/shortcodes/membership/membership-form-reminder.html @@ -0,0 +1,6 @@ +{{- /* + membership-form-reminder: the reminder to fill the membership form, shown + after a payment completes. +*/ -}} +

    If you haven't already, please remember to fill the +PyBCN Membership Form.

    diff --git a/layouts/shortcodes/membership/membership-links.html b/layouts/shortcodes/membership/membership-links.html new file mode 100644 index 00000000..167057c5 --- /dev/null +++ b/layouts/shortcodes/membership/membership-links.html @@ -0,0 +1,9 @@ +{{- /* + membership-links: the two closing paragraphs shared by the membership, + membership-thanks and membership-cancel pages. + + The three pages each carried their own copy in raw HTML, and all three + copies closed the first paragraph with "" instead of "

    ". +*/ -}} +

    You can find more information about the association here.

    +

    If you have any doubt, please don't hesitate to contact us.

    diff --git a/layouts/shortcodes/prose.html b/layouts/shortcodes/prose.html new file mode 100644 index 00000000..df2e5424 --- /dev/null +++ b/layouts/shortcodes/prose.html @@ -0,0 +1,11 @@ +{{- /* + prose: a block of markdown inside a shortcode that does not markdownify. + + Usage: + {{< grid-col md="6" >}} + {{< prose >}} + Ordinary **markdown** with [links](/somewhere). + {{< /prose >}} + {{< /grid-col >}} +*/ -}} +{{ .Inner | markdownify }} diff --git a/layouts/shortcodes/schedule.html b/layouts/shortcodes/schedule.html new file mode 100644 index 00000000..b1cfa8d7 --- /dev/null +++ b/layouts/shortcodes/schedule.html @@ -0,0 +1,52 @@ +{{- /* + schedule: a simple event timetable. + + Usage: + {{< schedule columns="3" >}} + ! Time | Track 1 | Track 2 + 09:30 | **Registration** + 10:30 | Workshop A | Workshop B + | **Track name** | **Other track name** + {{< /schedule >}} + + One line is one row. Cells are split on "|" and rendered as inline + markdown. A line that starts with "!" makes its cells header cells, which + a screen reader needs to say which track a session belongs to. A row with + fewer cells than there are columns makes its last cell span the rest, + which is how a whole event item such as a coffee break covers all tracks. + + Replaces a raw HTML table in content. The raw table had no header cells at + all, so no reader could tell which column was which track. +*/ -}} +{{- $cols := int (or (.Get "columns") "3") -}} +{{- $caption := .Get "caption" -}} + + {{- with $caption }} + + {{- end }} + + {{- range $line := split .Inner "\n" }} + {{- $line = trim $line " \t\r" }} + {{- if $line }} + {{- $header := hasPrefix $line "!" }} + {{- if $header }}{{ $line = trim (strings.TrimPrefix "!" $line) " " }}{{ end }} + {{- $cells := split $line "|" }} + {{- $n := len $cells }} + + {{- range $index, $cell := $cells }} + {{- $span := 1 }} + {{- if and (eq $index (sub $n 1)) (lt $n $cols) }} + {{- $span = add (sub $cols $n) 1 }} + {{- end }} + {{- $text := $.Page.RenderString (trim $cell " ") }} + {{- if $header }} + + {{- else }} + {{ $text }} + {{- end }} + {{- end }} + + {{- end }} + {{- end }} + +
    {{ . }}
    {{ $text }}
    diff --git a/themes/pybcn_theme/assets/scss/agenda.scss b/themes/pybcn_theme/assets/scss/agenda.scss index 3fe5d249..d4e639ea 100644 --- a/themes/pybcn_theme/assets/scss/agenda.scss +++ b/themes/pybcn_theme/assets/scss/agenda.scss @@ -146,18 +146,85 @@ $blockTimes15: 700,715,730,745,800,815,830,845,900,915,930,945,1000,1015,1030,10 } +/** + * Agenda legend. + * + * Built by the agenda_legend.html partial from structured front matter. + * It used to be a raw HTML blob, so the old "opacity: 0.7, full opacity on + * hover" trick cut the text contrast for every reader who never hovers. + * The text is now at full opacity. + */ .legend { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + gap: 0.4rem 1.1rem; + list-style: none; + padding: 0; + margin: 0 5px 25px 0; font-size: 0.9em; - opacity: 0.7; - text-align: right; - margin-bottom: 25px; - margin-right: 5px; - &:hover { - opacity: 1; + + li { + display: flex; + align-items: baseline; + gap: 0.35em; + } + + .legend_separator { + width: 1px; + align-self: stretch; + min-height: 1em; + background-color: #767676; + margin: 0 0.4rem; + } + + /* The gold of the agenda star is too light on a white page. */ + .fa-star.gold { + color: #8C6900; } } -i.green { color: #6CC417 } -i.yellow{ color: #FFFF33 } -i.red { color: red } +/** + * Experience level badge. + * + * Emitted by the level_badge.html partial. The text label carries the + * meaning, the dot is a redundant cue (WCAG 1.4.1 Use of Color). + * + * The badge draws its own light background, so dot contrast does not depend + * on the colour of the agenda cell behind it. Contrast of each dot against + * the #FFFFFF badge, against the 3:1 floor of WCAG 1.4.11 Non-text Contrast: + * beginner #2E7D32 5.1:1 + * intermediate #A15C00 5.2:1 + * advanced #CE1836 5.5:1 + * The #404040 border keeps the badge outline at 3:1 or better against every + * cell colour, the lightest of which is the #FF7900 orange at 3.9:1. + * + * The second selector repeats the first so that it outranks + * ".scheduleContainer .event span", which sets display block and width 100%. + */ +.level_badge, +.scheduleContainer .event .level_badge { + display: inline-flex; + align-items: baseline; + gap: 0.35em; + width: auto; + padding: 0 0.5em; + border: 1px solid #404040; + border-radius: 0.8em; + background-color: #FFFFFF; + color: #1F1F1F; + font-weight: 600; + white-space: nowrap; + vertical-align: baseline; + + i { + font-size: 0.7em; + } + + &.level_beginner i { color: #2E7D32; } + &.level_intermediate i { color: #A15C00; } + &.level_advanced i { color: #CE1836; } +} + i.gold { color: #FFD700 } diff --git a/themes/pybcn_theme/assets/scss/shortcodes.scss b/themes/pybcn_theme/assets/scss/shortcodes.scss new file mode 100644 index 00000000..5db28c59 --- /dev/null +++ b/themes/pybcn_theme/assets/scss/shortcodes.scss @@ -0,0 +1,74 @@ +/** + * Styles for the content shortcodes in layouts/shortcodes. + * + * These replace inline style attributes and obsolete elements that used to + * sit in the markdown of content/. Content now names a shortcode and the + * presentation lives here. + */ + +/* bordered-col with chevrons="true": the chevron before each card link. + * The contact page used to put a inside + * every link in the markdown. */ +.bordered_col.with_chevrons p a::before { + content: "\f054"; + font-family: "Font Awesome 5 Free"; + font-weight: 900; + margin-right: 0.4em; +} + +/* logo-row and logo: replaces
    and per image inline widths. */ +.logo_row { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 20px; + margin: 20px 0; + + .logo_row_item { + max-width: 100%; + height: auto; + } +} + +/* google-embed: replaces the inline "border-width:0" and the fixed width. */ +.google_embed { + width: 100%; + border: 0; +} + +/* schedule: the timetable of an archived event page. The raw table it + * replaces had no styling and no header cells. */ +.schedule_table { + width: 100%; + margin-bottom: 1.5rem; + border-collapse: collapse; + + caption { + caption-side: top; + padding-bottom: 0.5rem; + font-weight: bold; + color: inherit; + } + + th, + td { + padding: 0.4rem 0.6rem; + border-bottom: 1px solid #d6d6d6; + text-align: left; + vertical-align: top; + } + + th { + border-bottom: 2px solid #767676; + } +} + +/* Images written as markdown in a page body. The archived event pages used + * to set width:100% with an inline style attribute. max-width keeps an image + * inside its column without stretching a small one. */ +.main_column img, +.bordered_col img { + max-width: 100%; + height: auto; +} diff --git a/themes/pybcn_theme/assets/scss/style.scss b/themes/pybcn_theme/assets/scss/style.scss index 56b5a231..ec0ea447 100644 --- a/themes/pybcn_theme/assets/scss/style.scss +++ b/themes/pybcn_theme/assets/scss/style.scss @@ -13,3 +13,4 @@ @import 'agenda'; @import 'home'; @import 'monthly_events'; +@import 'shortcodes'; diff --git a/themes/pybcn_theme/layouts/_default/single.html b/themes/pybcn_theme/layouts/_default/single.html index d177bdde..2ecb7b7d 100644 --- a/themes/pybcn_theme/layouts/_default/single.html +++ b/themes/pybcn_theme/layouts/_default/single.html @@ -1,8 +1,16 @@ {{ define "main" }} +{{- /* + mainColumn in front matter keeps the narrower reading column that the + archived event pages used to build with their own container, row and + col-md-9 divs inside the page body. Those divs were raw HTML in markdown, + and they duplicated the wrappers this template already provides. +*/ -}} +{{ $narrow := .Params.mainColumn }} +
    -
    -
    +
    +
    {{ .Content }} diff --git a/themes/pybcn_theme/layouts/partials/agenda.html b/themes/pybcn_theme/layouts/partials/agenda.html index 48597675..fd322625 100644 --- a/themes/pybcn_theme/layouts/partials/agenda.html +++ b/themes/pybcn_theme/layouts/partials/agenda.html @@ -20,11 +20,7 @@ -{{ if .legend }} -
    - {{ .legend | safeHTML }} -
    -{{ end }} +{{ partial "agenda_legend.html" .legend }}
    @@ -43,23 +39,7 @@

    - {{ if eq $event.type "talk" }} - - {{ else if eq $event.type "coffee" }} - - {{ else if eq $event.type "lunch" }} - - {{ else if eq $event.type "photo" }} - - {{ else if eq $event.type "workshop" }} - - {{ else if eq $event.type "group" }} - - {{ else if eq $event.type "qa" }} - - {{ else if eq $event.type "lightning" }} - - {{ end }} + {{ partial "event_type_icon.html" $event.type }} {{ if $event.description }} @@ -97,10 +77,10 @@

    Topic: {{ . }} {{ end }} {{ with $event.python_level }} - Python level: {{ . | safeHTML }} + Python level: {{ partial "level_badge.html" . }} {{ end }} {{ with $event.topic_level }} - Topic level: {{ . | safeHTML }} + Topic level: {{ partial "level_badge.html" . }} {{ end }} {{ with $event.video }} Video diff --git a/themes/pybcn_theme/layouts/partials/agenda_legend.html b/themes/pybcn_theme/layouts/partials/agenda_legend.html new file mode 100644 index 00000000..708a5da8 --- /dev/null +++ b/themes/pybcn_theme/layouts/partials/agenda_legend.html @@ -0,0 +1,35 @@ +{{- /* + agenda_legend: render the agenda legend from structured front matter. + + Context: the "legend" list of an event page. Each item is one of: + - type: an entry type from event_types.html + label: optional. Overrides the default label + - level: beginner, intermediate or advanced + - separator: true a visual group break, hidden from screen readers + + The legend used to be one raw HTML string rendered with safeHTML, which + let any merged pull request inject script into every agenda page. Front + matter now carries tokens only, and this partial owns the markup. +*/ -}} +{{- $types := partialCached "event_types.html" "event_types" -}} +{{- with . }} +
      + {{- range . }} + {{- if .separator }} + + {{- else if .level }} +
    • {{ partial "level_badge.html" .level }}
    • + {{- else if .type }} + {{- $token := lower (trim (printf "%v" .type) " ") -}} + {{- $entry := index $types $token -}} + {{- if $entry }} +
    • {{ partial "event_type_icon.html" $token }} {{ default $entry.label .label }}
    • + {{- else }} + {{- warnf "agenda_legend: unknown legend type %q." $token -}} + {{- end }} + {{- else }} + {{- warnf "agenda_legend: legend item needs one of type, level or separator. Got %v." . -}} + {{- end }} + {{- end }} +
    +{{- end -}} diff --git a/themes/pybcn_theme/layouts/partials/event_detail.html b/themes/pybcn_theme/layouts/partials/event_detail.html index 346faf94..7c1e46ed 100644 --- a/themes/pybcn_theme/layouts/partials/event_detail.html +++ b/themes/pybcn_theme/layouts/partials/event_detail.html @@ -8,21 +8,7 @@ @@ -53,10 +39,10 @@