diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 719026334..68fce95ae 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -64,7 +64,7 @@ jobs: - name: Install dependencies # pillow: bin/check-content reads every person photo to warn about - # one with no colour. Without it the check runs and says it skipped + # one with no color. Without it the check runs and says it skipped # that. run: pip install pyyaml pillow diff --git a/AGENTS.md b/AGENTS.md index fca2cd84a..5cf82c9d5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -120,7 +120,7 @@ says how to install it when it is absent. **`unsafe=true` in `[markup.goldmark.renderer]`.** Raw HTML in front matter and page bodies renders unescaped. Two content files still carry it, `content/events/pyday_bcn/pyday_bcn_2018.md` and `pyday_bcn_2019.md`, which -are pre-Hugo programmes pasted in as tables. So **assume any content field +are pre-Hugo programs pasted in as tables. So **assume any content field can inject HTML**, and never add a field that reaches a template through `safeHTML`. `bin/check-html-safety` rejects dangerous markup in content and `bin/check-rendered` checks the built pages; both run on every pull request. @@ -146,12 +146,12 @@ problem somebody else has to find. the talk and meetup records. Writing them into a person's front matter guarantees they will eventually contradict the data. -**A programme is two lists, not one.** An event page carries `agenda` (the grid: +**A program is two lists, not one.** An event page carries `agenda` (the grid: `start`, `track_length`, `room`, and either a `talk` id or its own `label` and `type`), `talks` (the content: `title`, `speaker`, `description`, `language`, `topic`, `duration_minutes`, `links`), and `rooms` (`id` and `name`). They are separate because one talk can take several slots, and because a photo of the -gallery links to a talk by id, which a row of a grid cannot give it. The colour +gallery links to a talk by id, which a row of a grid cannot give it. The color of a block and the end of a slot are computed, not stored: see `partials/agenda_entry.html`. **A time is always a quoted string.** YAML 1.1 reads an unquoted `9:00` as the integer 540, sexagesimal, so Hugo renders it @@ -184,7 +184,7 @@ attribute, not a title. Hosting one meetup is not being an organizer. **RSVPs are not attendance.** `rsvps.attendedCount` is zero on 282 of the 285 events of the export, so the only figure available is who said yes on Meetup. -Render it as registrations. The figure was 205 of 207 while only the +Render it as RSVPs. The figure was 205 of 207 while only the `python-barcelona` group was read; the import reads `pyladies-bcn` as well. **No personal data beyond what is already published.** Never render email diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8482745b..cbb9845be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ same text the site publishes at [pybcn.org/pybcn_association/coc/](https://pybcn.org/pybcn_association/coc/), which renders that file. -## Licence +## License The code of the site is under the [MIT License](LICENSE) and the content is under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). @@ -41,7 +41,7 @@ is edited there, and a change made on `master` is lost on the next deploy. **You do not need Git, GitHub, or any of the rest of this file.** -If you have spoken at one of our events, or you organise with us, you may have +If you have spoken at one of our events, or you organize with us, you may have a card on the [organizers page](https://pybcn.org/pybcn_association/organizers/) or on the page of the event. Clicking it opens what the site holds about you. To change any of it, or to have it removed, **send an email to @@ -105,7 +105,7 @@ Edit the file on GitHub, or clone the repository and follow the steps below. to see which ones have no page yet, then `bin/new-meetup `. It writes the page from the public event page: the title, the day, the venue, the number of - registrations, the source URL, and the group. It writes no talk, because the + RSVPs, the source URL, and the group. It writes no talk, because the announcement says them in prose: pass `--description` to print that prose, and see [Import a meetup](README.md#import-a-meetup) for the rest of the path, which is the same one the 268 pages of the archive came through. @@ -160,7 +160,7 @@ What each check is for: | Check | Fails when | |---|---| | Build the site | Hugo cannot build, or emits a warning | -| `bin/check-content` | Front matter does not parse, a person `id` does not match its filename, an id is duplicated, a declared photo is missing, an event references a person or sponsor that does not exist, a social URL has the wrong shape, a field is empty, or an `end_date` is not later than `date`. It warns, without failing, about a photo that is too small or has no colour | +| `bin/check-content` | Front matter does not parse, a person `id` does not match its filename, an id is duplicated, a declared photo is missing, an event references a person or sponsor that does not exist, a social URL has the wrong shape, a field is empty, or an `end_date` is not later than `date`. It warns, without failing, about a photo that is too small or has no color | | `bin/check-html-safety` | Content carries raw HTML that turns a content change into script execution, a redirect, a credential prompt, or a page overlay. See [Content safety check](README.md#content-safety-check) | | `bin/check-rendered` | The built pages carry that same markup, which catches a template that produces it even when no content file does, or they link to anything over `http`. See [Rendered page check](README.md#rendered-page-check) | | `bin/canon.py --selftest` | The one normalization of imported text stops being idempotent, or changes what it strips | diff --git a/LICENSING.md b/LICENSING.md index 47af6aee5..ed7a16f5f 100644 --- a/LICENSING.md +++ b/LICENSING.md @@ -2,12 +2,12 @@ This repository holds the source of [pybcn.org](https://pybcn.org/), the site of the Associació Python Barcelona (PyBCN). It holds three kinds of thing, and -one licence does not fit all of them: the code of the site, the text of the +one license does not fit all of them: the code of the site, the text of the site, and material that the association publishes but does not own. This file -says which licence covers which path, and which paths no licence covers at all. +says which license covers which path, and which paths no license covers at all. -GitHub reads the licence of a repository from the `LICENSE` file alone, and a -second licence in that file stops the detection. So `LICENSE` holds the MIT +GitHub reads the license of a repository from the `LICENSE` file alone, and a +second license in that file stops the detection. So `LICENSE` holds the MIT License text and nothing else, and everything else about licensing is here. ## Code: MIT License @@ -35,7 +35,7 @@ of it. ## Content: CC BY-SA 4.0 The text of the site is licensed under the Creative Commons -Attribution-ShareAlike 4.0 International licence (CC BY-SA 4.0): +Attribution-ShareAlike 4.0 International license (CC BY-SA 4.0): - `content/`, except `content/people/`, see [Person pages](#person-pages). - `README.md` and `CONTRIBUTING.md`. @@ -48,12 +48,12 @@ Deed: Legal code: Attribute the text to "Python Barcelona (PyBCN), https://pybcn.org/". The -licence requires attribution, a link to the licence, a note of any change, and -the same licence on any adaptation. +license requires attribution, a link to the license, a note of any change, and +the same license on any adaptation. The full legal code is not copied here. Creative Commons keeps the canonical text at the URL above and says a link to it is enough, and a copy in this -repository would be a second licence text at the root, which is what confuses +repository would be a second license text at the root, which is what confuses the detection described above. ### Code of conduct @@ -63,16 +63,16 @@ the detection described above. licensed under [CC BY-SA 3.0 Unported](https://creativecommons.org/licenses/by-sa/3.0/). The adaptation is licensed under CC BY-SA 4.0, like the rest of the content, so -the whole repository is on one version of the licence family. +the whole repository is on one version of the license family. -The licence of the original permits that. Section 4(b) of the +The license of the original permits that. Section 4(b) of the [CC BY-SA 3.0 legal code](https://creativecommons.org/licenses/by-sa/3.0/legalcode) says that an Adaptation may be distributed under "(ii) a later version of this License with the same License Elements as this License", and section 1 names those elements: "Attribution, ShareAlike". CC BY-SA 4.0 is a later -version of that licence, and its License Elements are Attribution and +version of that license, and its License Elements are Attribution and ShareAlike. The same section 4(b) requires the notices that refer to the -licence of the original to stay intact, so the file keeps its attribution to +license of the original to stay intact, so the file keeps its attribution to PyLadies and the mention of CC BY-SA 3.0, and adds the link to CC BY-SA 4.0. ShareAlike is also why the file cannot go under the MIT License: an @@ -82,8 +82,8 @@ one. ## Not licensed The paths below are published on the site but are not covered by either -licence, because the rights in them are not the association's to give. A -licence that promised more than that would tell people they may do things they +license, because the rights in them are not the association's to give. A +license that promised more than that would tell people they may do things they may not. ### Photographs of people @@ -95,7 +95,7 @@ taken at PyBCN events. The people on this site sent their own photograph for publication on it. Anyone who did not want one did not send one, and the site shows a silhouette instead. The association publishes those photographs with the permission of -the people in them, given for that purpose. That permission is not a licence +the people in them, given for that purpose. That permission is not a license for anyone else to reuse a photograph, for two reasons: - The copyright in a photograph belongs to whoever took it. Giving PyBCN a @@ -105,7 +105,7 @@ for anyone else to reuse a photograph, for two reasons: would let a stranger reuse and adapt the image, commercially, for ever. Under Spanish law (Ley Orgánica 1/1982) the right to one's own image is a personality right and the consent is revocable, so it cannot become a - perpetual and irrevocable licence, which is what CC BY-SA is. + perpetual and irrevocable license, which is what CC BY-SA is. So the photographs are not licensed. They are published with the permission of the people in them, and that permission can be withdrawn. The event @@ -141,7 +141,7 @@ association publishes the text, it does not own it, and it cannot license it. There is a second reason, specific to these pages. A person can ask the association to erase their page, and the GDPR (Article 17.2) then obliges the association to take reasonable steps to tell anyone else holding a copy that -erasure was requested. A licence that invites lawful copies of a person's +erasure was requested. A license that invites lawful copies of a person's entry multiplies the copies the association would have to chase, and works against the erasure it has to be able to deliver. @@ -158,14 +158,14 @@ case (section 2(b)(2) of the legal code). The PyBCN logo and its variants (`themes/pybcn_theme/assets/images/logo.png`, `themes/pybcn_theme/assets/images/favicon.png`, `static/favicon.ico`, and the files under `static/images/backgrounds/`) -identify the association. They are not covered by the content licence: use +identify the association. They are not covered by the content license: use them to refer to PyBCN, not to suggest that PyBCN endorses something it has not seen. The PyLadies name and logo in that same folder are not the association's. ### Third-party libraries -Each of these keeps its own licence, and the notice inside each file stays +Each of these keeps its own license, and the notice inside each file stays with it: - `themes/pybcn_theme/assets/vendor/`: jQuery 3.3.1 (MIT), jQuery Easing diff --git a/README.md b/README.md index 206501bab..26bda7514 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ The pages of the archive were written from the Meetup export of both groups, the X exports of the association, the playlists of our channel, the records pyvideo keeps of PyData Barcelona 2017, and the frozen copies of the old site under `static/archives/`. Those sources, the tools that read them, and the -reports of the import live in a separate repository of this organisation, +reports of the import live in a separate repository of this organization, `pybcn/pybcn-archive`, which is **private**: a copy of a public page is not a secret, but 950 Meetup comments with the name of whoever wrote them, and the email addresses, the phone numbers, and the personal profiles that the event @@ -229,7 +229,7 @@ About the creation of new sponsors, the `themes/pybcn_theme/archetypes/sponsors. Every person photo is a square, cut once in the repository rather than on each build. `bin/square-photos` does the cutting: it finds the face with OpenCV, -crops the largest square it can centre on that face, and resizes to at most +crops the largest square it can center on that face, and resizes to at most 800px, which is what the 2x variant of a 400px grid slot needs. It never enlarges, because a 200px photo blown up to 800 is the same picture in four times the bytes. @@ -298,7 +298,7 @@ function in `bin/import-meetups`: `title`, `date`, `year`, `venue`, `attendance`, `meetup_url`, and `group`. `attendance` is who said yes on Meetup, not who came. -It refuses an event that is not `PAST`, because the registrations are not +It refuses an event that is not `PAST`, because the RSVPs are not final and the archive records what happened, and an event whose title says PyDay or PyData, because the large editions have their own pages. `--force` overrides both. It refuses to overwrite a page that is already there. @@ -388,8 +388,8 @@ Each event in the list can indicate: #### Experience levels `python_level` and `topic_level` take a token, never markup. The site renders -each token as a badge with a coloured dot and the matching text label, so the -level does not depend on colour alone: +each token as a badge with a colored dot and the matching text label, so the +level does not depend on color alone: | Token | Label | Dot | |---|---|---| @@ -557,7 +557,7 @@ The people behind the events, the speakers, the organizers, the venues, and the sponsors, are named on the pages of the site, which stay current on their own. `static/humans.txt` points at both. -## Licence +## License The code of the site (the templates, the stylesheets, the scripts, the workflows, and the configuration) is under the [MIT License](LICENSE). The @@ -568,5 +568,5 @@ photographs of people, the person pages, the sponsor logos, the association's own logos, the third-party libraries, and the archived sites are not licensed, each for a reason of its own. [LICENSING.md](LICENSING.md) lists every path and says why. The [code of conduct](CODE_OF_CONDUCT.md) was adapted from the -PyLadies one, which is under CC BY-SA 3.0; that licence allows the adaptation +PyLadies one, which is under CC BY-SA 3.0; that license allows the adaptation to move to 4.0, and LICENSING.md says how. diff --git a/bin/check-content b/bin/check-content index 01253cf27..542d167bb 100755 --- a/bin/check-content +++ b/bin/check-content @@ -4,7 +4,7 @@ Catches the mistakes that a Hugo build does not: a person id that does not match its filename, a duplicate id, a page that lists a person or sponsor id with no page behind it, a declared photo with no file behind it, and a -remote photo_url. It warns about a person photo with no colour in it. +remote photo_url. It warns about a person photo with no color in it. For an event photo gallery it catches what the template drops in silence: a declared photo with no file, a photo with no caption, a photo that points at @@ -42,7 +42,7 @@ import tomllib import yaml # Pillow is the library bin/square-photos needs, and pr.yml installs it for -# this check. A machine without it still runs every other check: the colour +# this check. A machine without it still runs every other check: the color # check reports once that it did not run, so the gap is visible and not an # error. try: @@ -239,11 +239,11 @@ def check_photos(people): saturation = photo_saturation(found) if saturation is not None and saturation < PHOTO_MIN_SATURATION: - warn(path, f"photo '{photo}' is black and white (colour " + warn(path, f"photo '{photo}' is black and white (color " f"{saturation:.1f}, under {PHOTO_MIN_SATURATION}). It " f"looks like the others on a screen that greys them on " f"hover, and grey on a phone and in the modal, where " - f"the others are in colour. Ask for a colour photo.") + f"the others are in color. Ask for a color photo.") report_small(small) if Image is None and people: note("Pillow is not installed, so the black and white photo check did " @@ -258,21 +258,21 @@ PHOTO_MAX_BYTES = 1_000_000 # Measured on the 130 photos of October 2026, ten score 0.01 or less and the # next one 9.5, so any value from 1 to 9 splits the two groups. 4 keeps the # grey group clear of JPEG chroma noise, which reached 0.01, and leaves the -# muted colour photo nearest the line, at 9.5, more than twice that margin. +# muted color photo nearest the line, at 9.5, more than twice that margin. PHOTO_MIN_SATURATION = 4 def photo_saturation(path): - """Return the mean colour of a photo, or None when it cannot be measured. + """Return the mean color of a photo, or None when it cannot be measured. The person cards grey every photo with a CSS filter on a device that can hover, so a photo that is already black and white looks like the others there. On a phone and in the modal nothing greys them, and that photo is - the one grey face in a wall of colour. Only the person can fix it, with + the one grey face in a wall of color. Only the person can fix it, with another photo, so this is a warning and never an error. Two of the ten grey photos are stored as greyscale; the other eight are - RGB JPEGs with no colour in them, which no header can tell from a colour + RGB JPEGs with no color in them, which no header can tell from a color photo. So the pixels are read, through a 64px thumbnail: Pillow decodes a JPEG at a fraction of its size for that, and the 130 photos add about 0.7 s to the run, 0.4 s to 1.1 s. @@ -330,7 +330,7 @@ def check_gallery(people): continue talk_ids = talk_ids_of(path, data, people) - # Two models of a programme in one file. The migration to talks is + # Two models of a program in one file. The migration to talks is # closing this, and a file is expected to carry both while it runs, # so a warning: what it costs is a reader seeing the same session # twice, once from each. @@ -358,7 +358,7 @@ def talk_ids_of(path, data, people): photo of it shows the title of the first, and so does every slot. This used to run from check_gallery only, which skips a page with no - photos block. Two of the ten files that carry a programme have one, so + photos block. Two of the ten files that carry a program have one, so the speaker ids of 21 talks were checked and the other 113 were not, and those 113 were exactly the ones that needed it: they credited a speaker as free text, which an id check cannot see at all. The walk now runs for @@ -371,7 +371,7 @@ def talk_ids_of(path, data, people): talks = data.get("talks") or [] if not talks: # Not kept: there is nothing to report twice, and a page with no - # programme would otherwise count towards the coverage figure below. + # program would otherwise count towards the coverage figure below. return set() talk_ids = set() unnamed = [] @@ -894,12 +894,12 @@ def check_agenda(people): The page carries the grid (agenda) apart from the content (talks), joined by a talk id, and that join fails in silence: a slot that names a talk the page does not define renders as an empty block, which looks - like a gap in the programme and not like a mistake. + like a gap in the program and not like a mistake. - The colour of a block is no longer checked here, because it is no longer + The color of a block is no longer checked here, because it is no longer in the content. partials/agenda_entry.html gives every room of an event - one colour of the palette agenda.scss defines. The old check demanded a - colour on every entry, which is how the archive ended up with 157 of + one color of the palette agenda.scss defines. The old check demanded a + color on every entry, which is how the archive ended up with 157 of them that meant nothing. """ for path in sorted(CONTENT.rglob("*.md")): @@ -929,7 +929,7 @@ def check_rooms(path, data): room_id = room.get("id") if not room_id: error(path, f"room {position} has no id. A slot of the agenda " - f"names its room by id, and the colour of the block " + f"names its room by id, and the color of the block " f"comes from it.") elif room_id in found: error(path, f"room {position} repeats the id '{room_id}'. Two " @@ -970,7 +970,7 @@ def check_talks(path, data, people): if talk.get("type") not in ENTRY_TYPES: error(path, f"talk '{title}' has type '{talk.get('type')}', which " f"is not one of: {', '.join(sorted(ENTRY_TYPES))}") - # Optional: the printed programme of PyDay BCN 2018 gives no length + # Optional: the printed program of PyDay BCN 2018 gives no length # at all, so none of its talks stores one. A value that is there has # to be a number, because the end of the slot is computed from it. if "duration_minutes" in talk and not isinstance(talk["duration_minutes"], int): @@ -1438,13 +1438,13 @@ def check_slot(path, position, slot, rooms, talks): known = ", ".join(sorted(talks)) or "none" error(path, f"{where} names talk '{talk}', which this page does not " f"declare. The block renders empty, which reads as a gap " - f"in the programme. Use one of: {known}.") + f"in the program. Use one of: {known}.") if slot.get("speaker") is not None: error(path, f"{where} carries 'speaker' {slot['speaker']!r}, the " f"free-text field that 'speakers' replaced. Nothing " f"renders it. Use speakers, a list of ids of " f"content/people/, or leave the slot with none: the " - f"organising committee of an edition is not a person.") + f"organizing committee of an edition is not a person.") if talk is None: if slot.get("type") not in ENTRY_TYPES: error(path, f"{where} holds no talk and has type " @@ -1488,7 +1488,7 @@ def check_orphans(people, listed_people): credits the record, and the file carries no photo, no social link, no position, and no bio. The name is then the whole row, which is a published claim that this person was part of the association with - nothing behind it. Either the programme that names them is missing, and + nothing behind it. Either the program that names them is missing, and crediting the talk fixes the row, or the file is a leftover and goes. The uncredited records are reported together as one note, not one @@ -1499,7 +1499,7 @@ def check_orphans(people, listed_people): listed_people is the set check_listings collected from the front matter keys and from the speakers of the talks, so only a real listing counts. - A page that carries a programme and no people_sections, PyData Barcelona + A page that carries a program and no people_sections, PyData Barcelona 2017, PyDay BCN 2018, or PyDay BCN 2019, reaches its speakers through the talks alone. An earlier version searched the text of every page with a word-boundary regex, and a regex boundary sits between a letter and a diff --git a/bin/check-html-safety b/bin/check-html-safety index 8060333ba..93afe6ac2 100755 --- a/bin/check-html-safety +++ b/bin/check-html-safety @@ -99,7 +99,7 @@ PATTERNS = [ # background build a full page overlay with a phishing link in it. The # attribute is a finding unless its value passes SAFE_STYLE. ("style-attr", re.compile(r"(? is not touched by Hugo's render hook, so javascript:, @@ -170,7 +170,7 @@ def normalise_scheme(text): 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 + The offsets exist because the normalized 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. @@ -338,7 +338,7 @@ def scan_text(text, where, relpath, line_offset=0): for match in regex.finditer(haystack): if name == "style-attr" and benign_style(haystack, match.start()): continue - # A scheme match is found in the normalised text, which carries no + # A scheme match is found in the normalized text, which carries no # newlines. Map it back so the line number and the excerpt describe # the file the contributor has to edit. at = match.start() diff --git a/bin/check-rendered b/bin/check-rendered index a6e5c1903..0192def11 100755 --- a/bin/check-rendered +++ b/bin/check-rendered @@ -288,7 +288,7 @@ STYLE_CHARS = re.compile(r"[\x20-\x7e\t\n\r]*") # attribute table plus the grid properties the agenda writes. A deny list was # tried first and missed eight ways to hide or move an element (overflow, # zoom, offset-path, all, a negative length written -.5em or inside calc(), -# a zero font-size, a transparent colour, a rule inside @media), so the block +# a zero font-size, a transparent color, a rule inside @media), so the block # is now accepted only for what it is known to need. # # Before the grammar runs, the whole block is refused when it holds an @@ -510,7 +510,7 @@ ALLOWLIST = [ "of the page of its meetup (partials/session_videos.html, through " "partials/video_frame.html): a recording of a session has no page of " "its own, so the page of its day is the page about it. Three meetups " - "carry one. A listing or a programme grid prints a link and no frame"}, + "carry one. A listing or a program grid prints a link and no frame"}, {"path": "index.html", "kind": "iframe", "prefix": "https://www.youtube-nocookie.com/embed/", @@ -858,7 +858,7 @@ def scan(build, site_host): HEADING_EXEMPT = ("archives/",) HEADING = re.compile(r", and not a # repository, and a medium.com/@handle is a handle. The rule follows the @@ -241,7 +241,7 @@ def yaml_string(value): """Return value as a double quoted YAML scalar, on one line. The same escaping bin/import-meetups writes, plus the newline: a talk - description holds paragraphs, and the published programmes write those + description holds paragraphs, and the published programs write those as \\n inside a one line scalar. Only the backslash, the double quote, the newline, and the tab need escaping inside double quotes. """ diff --git a/bin/import-videos b/bin/import-videos index 959bbc530..3b37140a7 100755 --- a/bin/import-videos +++ b/bin/import-videos @@ -43,8 +43,8 @@ the export reads the day, the talk, and the speaker out of a video title, and three titles defeat it: a short name an uploader wrote for a long title ("PySpark and Arrow"), a live stream with no date in its title, and a live stream of a whole evening whose title names no talk. For each one a -person read the programme of its day and wrote the facts by id in -tools/parse_youtube.py of the pybcn-archive: the title the programme uses, +person read the program of its day and wrote the facts by id in +tools/parse_youtube.py of the pybcn-archive: the title the program uses, the event, whether the video is of one talk or of the whole session, and the reason. The record then carries "declared" in flags and in match, and declared_reason, with no candidates, because the person named the event @@ -77,8 +77,8 @@ How a video finds its talk, and what stops a wrong match: does, the video goes on that talk, on the day of that other event: the month in a title is a label the uploader typed weeks after the day, and a title that matches one talk of - the whole archive is a fact of the programme, so the - programme wins. Measured on 2026-10-13, six of the 83 videos + the whole archive is a fact of the program, so the + program wins. Measured on 2026-10-13, six of the 83 videos are placed that way, and each one is named in its own group of the report, with the day the title claims and the event that announced the talk, so a human always sees them. The @@ -225,7 +225,7 @@ def read_events(events_dir): # row of the grid, which is where the welcome of PyDay BCN 2020 # holds one (see partials/agenda_entry.html). No video is ever # written there by this script, because a monthly meetup has no - # grid, but a video already in place has to be recognised wherever + # grid, but a video already in place has to be recognized wherever # it sits or a second copy of it would be written. for slot in data.get("agenda") or []: if not isinstance(slot, dict) or slot.get("talk"): @@ -233,7 +233,7 @@ def read_events(events_dir): label = slot.get("label") or slot.get("type") or "a row of the grid" held.update({url: "the grid row '%s'" % label for url in videos_of(slot)}) # The recording of a whole session, which this script writes on the - # event (see the docstring), has to be recognised on a second run. + # event (see the docstring), has to be recognized on a second run. for entry in data.get("session_videos") or []: if isinstance(entry, dict) and entry.get("url"): held[entry["url"]] = "the session_videos block of the event" @@ -297,11 +297,11 @@ def classify(video, events): compare ambiguous two talks of the day match, so neither is written off_day no talk of the day matches, but exactly one talk of - another day does, so the programme wins over the label + another day does, so the program wins over the label in the title and the page of that other day gets the link other_day no talk of the day matches, and talks of two other days - do, so the programme cannot say which one and neither + do, so the program cannot say which one and neither is written no_talk no talk anywhere matches this title out_of_scope the export says this video belongs to no PyBCN event, @@ -389,7 +389,7 @@ def classify_declared(video, events): """Return (state, detail) for a record a person declared in the export. The declaration names the event in meetup_id and the talk by the title - the programme uses (see the docstring). The record has no candidates, + the program uses (see the docstring). The record has no candidates, because the person chose and the grammar did not, so the tests are: meetup_id names a page of this tree, the day of that page agrees with the record, and, for a video of one talk, exactly one talk of that page @@ -657,9 +657,9 @@ def report(groups, dry_run): % (plural(len(placed), "video"), plural(len(talks), "talk"), plural(len(pages), "page"))) # Counted apart from the line above on purpose: a video placed on a day - # its title does not name is a decision the programme took over the + # its title does not name is a decision the program took over the # label, and a human has to be able to see every one of them. - print("%s placed where the programme announced the talk, " + print("%s placed where the program announced the talk, " "not on the day the title says" % plural(len(off_day), "video")) print("%s written on the event as the recording of a whole session" % plural(len(groups["session"]), "video")) @@ -675,7 +675,7 @@ def report(groups, dry_run): for state, heading in ( ("ambiguous", "left out, two talks of the day match one video"), ("other_video", "left out, the talk already carries another video"), - ("other_day", "left out, the day in the title and the programme disagree"), + ("other_day", "left out, the day in the title and the program disagree"), ("no_talk", "left out, no talk of the archive carries this title"), ("no_session", "left out, a session recording with no page to go to"), ("no_declared", "left out, a declared record that names no page or no talk of this tree"), diff --git a/bin/new-meetup b/bin/new-meetup index da062ca23..0c3cb11d0 100755 --- a/bin/new-meetup +++ b/bin/new-meetup @@ -10,7 +10,7 @@ the shape of the front matter either. Give this script the URL of a past meetup and it writes content/events/meetups/-.md, with the same fields the import wrote, through the same function. The page it writes is complete as a page: -the day, the venue, the registrations, the source, and the group. +the day, the venue, the RSVPs, the source, and the group. Where the fields come from. The public event page carries the whole event as JSON, in the __NEXT_DATA__ script tag Meetup's own front end reads, so there @@ -31,7 +31,7 @@ What it does not write: records what happened and not how to register for something that is over. A person page, or a venue in data/venues.yaml. The script reports a venue - it does not recognise and writes nothing else: a new venue is a short name + it does not recognize and writes nothing else: a new venue is a short name somebody chooses. Anything about who came. The RSVP count is who said yes, it names nobody, @@ -296,7 +296,7 @@ def main(): if event.get("status") != "PAST" and not args.force: print("SKIP %s is %s, not PAST. The archive records what happened: run" % (url, (event.get("status") or "unknown").lower())) - print(" this after the day, when the registrations are final, or") + print(" this after the day, when the RSVPs are final, or") print(" pass --force.") skipped = True continue @@ -331,7 +331,7 @@ def main(): for path, record, event, state in written: venue = record["venue"]["name"] print("%s %s" % ("would write" if args.dry_run else "wrote", path)) - print(" %s, %s, %d registrations" + print(" %s, %s, %d RSVPs" % (record["dateTime"][:10], venue or "no venue", record["rsvps"]["yesCount"])) if venue and venues is not None and canon(venue) not in venues: print(" NEW VENUE data/venues.yaml does not name %r. Add a short name" % venue) diff --git a/bin/square-photos b/bin/square-photos index 62abbb91a..bfd667284 100755 --- a/bin/square-photos +++ b/bin/square-photos @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Crop the person photos to a square, centred on the face. +"""Crop the person photos to a square, centered on the face. The site serves every person photo as a square. Until now the square was cut at build time, which has two costs: the crop is chosen by a heuristic that @@ -9,7 +9,7 @@ than anything the site ever serves, 38 MB of them. This cuts the square once, in the repository, so the crop is reviewable in a pull request like any other change, and the build only has to resize. -The crop is centred on the face when OpenCV finds one, and on the upper middle +The crop is centered on the face when OpenCV finds one, and on the upper middle when it does not, because a portrait that is taller than it is wide almost always has the head in the top half. @@ -45,7 +45,7 @@ DEFAULT_SIDE = 800 def load(path): """Open a photo with its EXIF rotation applied. - One photo in the set carries Orientation 5. A browser honours that tag and + One photo in the set carries Orientation 5. A browser honors that tag and shows the picture upright, so the site looked right while every tool that reads the pixels directly saw it on its side. Applying the rotation here and dropping the tag leaves one truth instead of two. @@ -98,7 +98,7 @@ def find_face(path): return max(plausible or list(faces), key=lambda f: f[2] * f[3]) -# A square centred on a face near the edge does not fit, so the square has to +# A square centered on a face near the edge does not fit, so the square has to # shrink. It does not shrink below this, because a tight crop of a head with no # shoulders looks like a mugshot next to the others in the grid. MIN_FACE_MULTIPLE = 3.5 @@ -136,7 +136,7 @@ def crop_box(width, height, face): else: centre_x = width / 2 # The upper middle, not the middle: a portrait taller than it is wide - # has the head in the top half, and a centred crop cuts the forehead. + # has the head in the top half, and a centered crop cuts the forehead. centre_y = height / 2 if width >= height else height * 0.4 left = round(centre_x - side / 2) top = round(centre_y - side / 2) diff --git a/bin/titlematch.py b/bin/titlematch.py index 17812f2da..bb0c6d695 100644 --- a/bin/titlematch.py +++ b/bin/titlematch.py @@ -1,7 +1,7 @@ """The comparison form of a title, for finding one title inside a text. Two imports of this archive have the same problem: a title written for a -reader has to be recognised inside another string that carries it. +reader has to be recognized inside another string that carries it. bin/import-x-photos reads a tweet caption that quotes the title of the talk it photographs, and bin/import-videos reads the title of a YouTube upload that names the talk it recorded. The rule lives here, once, because a second @@ -24,7 +24,7 @@ accents decomposed and dropped, and every mark replaced by a space. This is the one place in this repository that folds an accent on purpose, and it is safe only because nothing it returns is ever stored or published. A title -printed with its own punctuation has to compare equal to the programme: +printed with its own punctuation has to compare equal to the program: "Models de regressio bayesians," in a post and "Models de regressió bayesians" in the front matter are the same title. @@ -132,7 +132,7 @@ def match_title(text, candidates, both_ways=False): (None, ""), ] -# One programme, folded once, as a caller passes it. +# One program, folded once, as a caller passes it. _TALKS = [ ("api-by-example", fold("API by example")), ("hacking-the-bcn-housing-market-scrapy", @@ -156,7 +156,7 @@ def match_title(text, candidates, both_ways=False): # Under the length guard, both ways: "comprehensions" alone is 14 # characters, but the folded text here is 11 and never matches. ("Comprehensi", True, None, []), - # Nothing of the programme is in this text. + # Nothing of the program is in this text. ("PyDayBCN 2020 Track 1 - Retrying, a better way by C. Adell", True, None, []), ("", True, None, []), diff --git a/config.toml b/config.toml index 9df87639c..3d19b69ae 100644 --- a/config.toml +++ b/config.toml @@ -60,7 +60,7 @@ timeout = "300s" # thomas-alisi (bin/check-content names them in a note). They get a page # all the same, with the photo, the bio, the position, or the links their # file carries, and the two-classes argument of #201 is the reason: taking -# the page away from the six whose programme has not been credited yet +# the page away from the six whose program has not been credited yet # would sort the people of the archive into the ones with a page and the # ones without, on a fact about the import and not about them. The # figure that used to be the point here, that 240 of the 378 records hold @@ -96,6 +96,10 @@ unsafe=true main_contact_email = "pybcn@googlegroups.com" short_name = "PyBCN" extended_name = "The Barcelona Python Association" + # The sentence a search engine shows for a page that says nothing about + # itself: the meta description of partials/head-meta.html falls back to + # it. One line, under 160 characters. + description = "Python Barcelona (PyBCN) is the Python community of Barcelona: monthly meetups since 2007, PyLadies BCN workshops, and the annual PyDay BCN conference." # Who the association is in law. Spanish law 34/2002 (LSSI-CE) article 10 # requires a site run by an association to publish its name, its address, @@ -107,7 +111,7 @@ unsafe=true # The values match the association's entry in the Registre d'Entitats de # la Generalitat de Catalunya, which is public open data: # https://analisi.transparenciacatalunya.cat/d/y6fz-g3ff - # Only the Management Board changes address, registry or registered_on: + # Only the Board changes address, registry or registered_on: # they describe the association as the register records it, not as # volunteers know it. The register names the register itself, not only # the number, because article 10 asks for the entry in the register and a diff --git a/content/events/meetups/2017-04-05-pydatabcn-2017-call-for-papers-mentoring-session.md b/content/events/meetups/2017-04-05-pydatabcn-2017-call-for-papers-mentoring-session.md index a6373cc56..e900aa811 100644 --- a/content/events/meetups/2017-04-05-pydatabcn-2017-call-for-papers-mentoring-session.md +++ b/content/events/meetups/2017-04-05-pydatabcn-2017-call-for-papers-mentoring-session.md @@ -10,5 +10,5 @@ group: PyBCN # out of the monthly list matches any title that says PyData or PyDay, and this # one says PyData without being the conference: it is the session where the # association helped people write a proposal for it. Both groups listed the same -# day, PyBCN with 19 registrations and PyLadies BCN with 3 more. +# day, PyBCN with 19 RSVPs and PyLadies BCN with 3 more. --- diff --git a/content/events/meetups/_index.md b/content/events/meetups/_index.md index b9313b156..1e16b83a0 100644 --- a/content/events/meetups/_index.md +++ b/content/events/meetups/_index.md @@ -16,7 +16,7 @@ description: "" # partials/meetup-events.html is a link to Meetup and not a list. # # What each file carries, and what it does not. The title, the day, the -# venue, the registrations, the source URL, and the group are copies of one +# venue, the RSVPs, the source URL, and the group are copies of one # field each, so they are as good as the export. The Meetup description is # not published: it is the door policy, "only register if you can attend", # the call for proposals, and a social media footer, and an archive records @@ -62,7 +62,7 @@ cascade: # attendance is the yesCount of the Meetup RSVPs. It is who said yes, not # who came: attendedCount is zero on almost every record. A page has to -# print it as registrations, the way AGENTS.md requires. +# print it as RSVPs, the way AGENTS.md requires. --- -Every meetup the association has run, from the first one in 2007. The programme of each one was read out of the Meetup announcement that published it, so 213 of these 268 pages carry the talks of the day as well as the day, the venue, and the number of registrations. The other 55 pages are the days whose announcement named no session: a study group, a coding dojo, a documentation sprint, a barbecue, a social gathering, or an early meetup whose announcement said only that there would be one. +Every meetup the association has run, from the first one in 2007. The program of each one was read out of the Meetup announcement that published it, so 213 of these 268 pages carry the talks of the day as well as the day, the venue, and the number of RSVPs. The other 55 pages are the days whose announcement named no session: a study group, a coding dojo, a documentation sprint, a barbecue, a social gathering, or an early meetup whose announcement said only that there would be one. diff --git a/content/events/monthly_events.md b/content/events/monthly_events.md index 4c430f7d0..0cf1b0614 100644 --- a/content/events/monthly_events.md +++ b/content/events/monthly_events.md @@ -14,4 +14,4 @@ meetupEvents: weight: 3 --- -The next meetup is announced on Meetup, which is also where the association takes the registrations for it. The ones that already happened are on this site: [every monthly meetup since 2007](/events/meetups/), 266 of them, each with the day, the venue, the group that ran it, and the number of people who signed up. +The next meetup is announced on Meetup, which is also where you RSVP for it. The ones that already happened are on this site: [every monthly meetup since 2007](/events/meetups/), 266 of them, each with the day, the venue, the group that ran it, and the number of RSVPs. diff --git a/content/events/other_events/django_pyladies_2022.md b/content/events/other_events/django_pyladies_2022.md index 95ab8d366..e225a2c9d 100644 --- a/content/events/other_events/django_pyladies_2022.md +++ b/content/events/other_events/django_pyladies_2022.md @@ -47,7 +47,7 @@ free_text_sections: - title: When and where id: when_and_where - content: It is scheduled for **Saturday 11th June** in Canòdrom - Ateneu d'Innovació Digital i Democràtica, from 9:00pm to 18:30pm CET. + content: It is scheduled for **Saturday 11th June** in Canòdrom - Ateneu d'Innovació Digital i Democràtica, from 9:00pm to 18:30pm CET. - title: Important dates id: important_dates @@ -137,8 +137,8 @@ numTracks: 1 eventTimes: ["9:00", "9:30", "10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", "17:00", "17:30", "18:00"] # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: room-actes diff --git a/content/events/other_events/hacktoberfest_2018.md b/content/events/other_events/hacktoberfest_2018.md index 85b17ecd8..bee4b96e7 100644 --- a/content/events/other_events/hacktoberfest_2018.md +++ b/content/events/other_events/hacktoberfest_2018.md @@ -17,7 +17,7 @@ description: "Hacktoberfest is an annual event across the world to encourage dev # No agenda, on purpose. The frozen page lists hours (a welcome talk and # breakfast at 10.00, project pitches at 10.15, a tutorial for beginners # at 10.30, and work from 10.45) but names no speaker and no talk. Writing -# that as a programme would invent a grid the day did not have, so the +# that as a program would invent a grid the day did not have, so the # frozen page keeps it and this one links there. people_sections: - title: Organizers diff --git a/content/events/pydatabcn/pydatabcn_2023.md b/content/events/pydatabcn/pydatabcn_2023.md index 1fa25e933..cb56b365b 100644 --- a/content/events/pydatabcn/pydatabcn_2023.md +++ b/content/events/pydatabcn/pydatabcn_2023.md @@ -102,8 +102,8 @@ legend: - type: sponsor # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: open-air-terrace @@ -240,7 +240,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDataBCN Organising Committee" + credited_as: "PyDataBCN 2023 organizers" track_length: 4 room: open-air-terrace type: group @@ -356,7 +356,7 @@ agenda: room: sala-dactes-ada-lovelace talk: lightning-talks-session - start: "17:30" - credited_as: "PyDataBCN Organising Committee" + credited_as: "PyDataBCN 2023 organizers" track_length: 4 room: sala-dactes-ada-lovelace type: group diff --git a/content/events/pyday_bcn/pyday_bcn_2016.md b/content/events/pyday_bcn/pyday_bcn_2016.md index 390ec23a4..aaa769d4f 100644 --- a/content/events/pyday_bcn/pyday_bcn_2016.md +++ b/content/events/pyday_bcn/pyday_bcn_2016.md @@ -35,7 +35,7 @@ heroBackground: /images/photos/people-pyday-2016.jpg # (measured 2026-10-14); check-content says a site that does not answer # over https is for its owner to fix, so the link stays. The venue level # follows the 2025 page, which lists Canòdrom among the organizers. This -# edition has no programme: the archive holds none, and bin/check-content +# edition has no program: the archive holds none, and bin/check-content # notes the gap. sponsors_text: | The sponsors and collaborators of the first PyDay, by the levels of the archived site of the edition. Also on the archived site: diff --git a/content/events/pyday_bcn/pyday_bcn_2018.md b/content/events/pyday_bcn/pyday_bcn_2018.md index c44e1a9d8..1c0624af5 100644 --- a/content/events/pyday_bcn/pyday_bcn_2018.md +++ b/content/events/pyday_bcn/pyday_bcn_2018.md @@ -12,7 +12,7 @@ menu: weight: 8 heroBackground: /images/photos/people-pyday-2016.jpg -# The programme of this edition, read from the page the association published +# The program of this edition, read from the page the association published # for it, which this repository keeps frozen at # static/archives/pybcn.org/pyday-bcn-2018/index.html. Its Agenda table gives # the time, the track, and the speaker of every session, and its "Workshops @@ -123,9 +123,9 @@ rooms: # reads them from here. # # This page declares no eventTimes, so no grid is rendered from this list. The -# programme a reader sees is that same frozen table. The list is here because +# program a reader sees is that same frozen table. The list is here because # a photo of the gallery joins to a talk by id, and because the nine photo -# days still to import need one shape for a programme and not two. +# days still to import need one shape for a program and not two. agenda: - start: "10:30" track_length: 1 @@ -215,7 +215,7 @@ agenda: # of a screen that says nothing about the day. # # A photo carries a talk only when its caption names that talk. The eight -# that do are the eight sessions of the programme above, each announced as +# that do are the eight sessions of the program above, each announced as # it started. The other eight are the room, the welcome slides, and lunch. # The one photo of this day: the group photo when the day has one, and the # picture that says most about it when it does not. It is what the carousel @@ -322,7 +322,7 @@ sponsor_levels: We are excited and glad to announce that we are organizing the second edition of PyDay in Barcelona!

-PyDay Barcelona 2018 is going to take place on November 24th at PuntMultimèdia (Espanya Industrial, Sants), full of FREE workshops, talks and contests for the local Python community and an opportunity to spread the word of its existence to other people that could be interested in Python. +PyDay Barcelona 2018 is going to take place on November 24th at PuntMultimèdia (Espanya Industrial, Sants), full of FREE workshops, talks and contests for the local Python community and an opportunity to spread the word of its existence to other people that could be interested in Python.

What is PyDay Barcelona 2018 about?

@@ -330,7 +330,7 @@ PyDay Barcelona 2018 has the aim of expanding the local Python community. It wil

Join the event

-Eventbrite - PyDay Barcelona 2018 +Eventbrite - PyDay Barcelona 2018

Agenda

@@ -415,7 +415,7 @@ In this short workshop we give a quick and dirty introduction to pytorch. You wi
  • We assume that you are familiar with python, have some basic knowledge about neural network.
  • You will get the best experience if you bring a notebook with access to python (I'll use version 3.6) with numpy, pandas, jupyter, pytorch, matplotlib, pillow and opencv.
  • -
  • Guide to install Pytorch.
  • +
  • Guide to install Pytorch.

Data analysis with Jupyter Notebook, Pandas and Plotly

Speaker: Natàlia Padilla (@nataliasirera) and Laura Pérez (@laura-perez-mayos) (@PyLadiesBCN)
@@ -424,12 +424,12 @@ In this short workshop we give a quick and dirty introduction to pytorch. You wi Level: Beginner
Requirements: a laptop + Jupyter + Pandas + Plotly + an appetite for learning!
Installation:
-• Option 1: Install Anaconda anaconda.com/download
+• Option 1: Install Anaconda anaconda.com/download
• Option 2: Execute on the terminal: pip install jupyter pandas plotly

Mirror, mirror on the wall, who is the fairest of them all? (Introduction to OpenCV)

Speaker: Ismael Benito (@ismansiete)
Language: English
-Description: An introduction to OpenCV for NumPy-Scipy-Matplotlib stack users. Starting with Anaconda pre-compiled versions, specially from Menpo project (https://anaconda.org/menpo/opencv3). Covering inputs and outputs, from basic image handling, such as: 'imread', 'imshow', 'imwrite', etc; to video streams. Some basics in color treatment and thresholding techniques. Also, fundamentals of image warping and cropping. Finally, a small project to be able to find a specific object, for example a QR Code, in a scene and trimmed it.
+Description: An introduction to OpenCV for NumPy-Scipy-Matplotlib stack users. Starting with Anaconda pre-compiled versions, specially from Menpo project (https://anaconda.org/menpo/opencv3). Covering inputs and outputs, from basic image handling, such as: 'imread', 'imshow', 'imwrite', etc; to video streams. Some basics in color treatment and thresholding techniques. Also, fundamentals of image warping and cropping. Finally, a small project to be able to find a specific object, for example a QR Code, in a scene and trimmed it.
Level: Intermediate
Requirements: A laptop with a Miniconda/Anaconda distribution. You must create an environment:

@@ -459,7 +459,7 @@ apt install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-d

Speaker: Jordi Guix
Language: English
Description: Learn how to access and manage big data with Python. How to access to DB, basic CRUD operations (Create, Read, Update, Delete) and overview of advance operations.
-Get the workshop materials.

+Get the workshop materials.

  1. Presentació (5 min)
  2. Breu introducció de: (10 - 15 min)

    Organizando chistes con NLP

    Speaker: Julio Martínez (@liopic)
    diff --git a/content/events/pyday_bcn/pyday_bcn_2019.md b/content/events/pyday_bcn/pyday_bcn_2019.md index fd3c3f0d8..c1dcf5360 100644 --- a/content/events/pyday_bcn/pyday_bcn_2019.md +++ b/content/events/pyday_bcn/pyday_bcn_2019.md @@ -47,7 +47,7 @@ sponsor_levels: sponsors: [kschool, satellogic, blueliv] name: Silver -# The programme of this edition, read from the printed agenda that the live +# The program of this edition, read from the printed agenda that the live # thread on X photographed (tweet 1195637939285430272, the photo on this page). # The Google Calendar embed that held it is gone, and the Meetup description # never carried it, so that photograph is the source. Titles are copied from @@ -181,10 +181,10 @@ rooms: # corrects now lives. # # This page declares no eventTimes, so no grid is rendered from this list. -# The programme a reader sees is the Google Calendar embed in the body, which +# The program a reader sees is the Google Calendar embed in the body, which # is what the association published. The list is here because a photo of the # gallery joins to a talk by id, and because the nine photo days still to -# import need one shape for a programme and not two. +# import need one shape for a program and not two. agenda: # The sheets print the opening keynote in all three tracks at 9:30, so it is # one slot across the grid. The closing keynote has no slot: it is not on @@ -264,7 +264,7 @@ agenda: level: beginner # Photos published by PyBCN on the day. One per tweet, so no two share a -# caption, and the caption is also the alt text. PyBCN organisers took them. +# caption, and the caption is also the alt text. PyBCN organizers took them. # The page credits the account that published them, which is the part the # post itself proves. # The one photo of this day: the group photo when the day has one, and the diff --git a/content/events/pyday_bcn/pyday_bcn_2020.md b/content/events/pyday_bcn/pyday_bcn_2020.md index 7938baeef..5e5cdc559 100644 --- a/content/events/pyday_bcn/pyday_bcn_2020.md +++ b/content/events/pyday_bcn/pyday_bcn_2020.md @@ -72,8 +72,8 @@ numTracks: 2 eventTimes: ["16:00", "16:15", "16:30", "16:45", "17:00", "17:15", "17:30", "17:45", "18:00", "18:15", "18:30", "18:45", "19:00", "19:15", "19:30", "19:45", "20:00", "20:15", "20:30"] # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: youtube-track1-and-track2 diff --git a/content/events/pyday_bcn/pyday_bcn_2021.md b/content/events/pyday_bcn/pyday_bcn_2021.md index b8e262f3d..9776339e6 100644 --- a/content/events/pyday_bcn/pyday_bcn_2021.md +++ b/content/events/pyday_bcn/pyday_bcn_2021.md @@ -93,8 +93,8 @@ legend: - type: sponsor # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: open-air-terrace @@ -260,7 +260,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDay BCN 2021 Organising Committee" + credited_as: "PyDay BCN 2021 organizers" track_length: 4 room: open-air-terrace type: group @@ -405,7 +405,7 @@ agenda: topic_level: beginner requirements: "Try to run Nautobot Lab (https://github.com/nautobot/nautobot-lab) in Docker, as we'll use it as support during the workshop." - start: "17:30" - credited_as: "PyDay BCN 2021 Organising Committee" + credited_as: "PyDay BCN 2021 organizers" track_length: 4 room: all-rooms type: group diff --git a/content/events/pyday_bcn/pyday_bcn_2022.md b/content/events/pyday_bcn/pyday_bcn_2022.md index faf8f8ba1..8b14b618e 100644 --- a/content/events/pyday_bcn/pyday_bcn_2022.md +++ b/content/events/pyday_bcn/pyday_bcn_2022.md @@ -125,8 +125,8 @@ legend: - level: advanced # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: sala-dactes-ada-lovelace @@ -261,7 +261,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDay BCN 2022 Organising Committee" + credited_as: "PyDay BCN 2022 organizers" track_length: 3 room: sala-dactes-ada-lovelace type: group diff --git a/content/events/pyday_bcn/pyday_bcn_2023.md b/content/events/pyday_bcn/pyday_bcn_2023.md index 5797cebed..d91ea54d6 100644 --- a/content/events/pyday_bcn/pyday_bcn_2023.md +++ b/content/events/pyday_bcn/pyday_bcn_2023.md @@ -126,8 +126,8 @@ legend: - level: advanced # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: room-b5 @@ -262,7 +262,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDay BCN 2023 Organising Committee" + credited_as: "PyDay BCN 2023 organizers" track_length: 3 room: room-b5 type: group diff --git a/content/events/pyday_bcn/pyday_bcn_2024.md b/content/events/pyday_bcn/pyday_bcn_2024.md index e113d8567..d3f836c16 100644 --- a/content/events/pyday_bcn/pyday_bcn_2024.md +++ b/content/events/pyday_bcn/pyday_bcn_2024.md @@ -121,8 +121,8 @@ legend: - level: advanced # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: sala-dactes-ada-lovelace @@ -269,7 +269,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDay BCN 2024 Organizing Committee" + credited_as: "PyDay BCN 2024 organizers" track_length: 4 room: sala-dactes-ada-lovelace type: group diff --git a/content/events/pyday_bcn/pyday_bcn_2025.md b/content/events/pyday_bcn/pyday_bcn_2025.md index 9f1c0635b..f8c6c3959 100644 --- a/content/events/pyday_bcn/pyday_bcn_2025.md +++ b/content/events/pyday_bcn/pyday_bcn_2025.md @@ -156,8 +156,8 @@ legend: - level: advanced # The rooms of this edition, in the order the grid first names them. A room is -# a record with an id because the colour of a block now comes from it: the -# template gives every room of an event one colour of the agenda palette and +# a record with an id because the color of a block now comes from it: the +# template gives every room of an event one color of the agenda palette and # keeps it for the whole day. See partials/agenda_entry.html. rooms: - id: sala-dactes-ada-lovelace @@ -386,7 +386,7 @@ talks: # the integer 540. agenda: - start: "9:00" - credited_as: "PyDay BCN 2025 Organising Committee" + credited_as: "PyDay BCN 2025 organizers" track_length: 4 room: sala-dactes-ada-lovelace type: group diff --git a/content/people/_content.gotmpl b/content/people/_content.gotmpl index 41fcc3227..d2b2f1343 100644 --- a/content/people/_content.gotmpl +++ b/content/people/_content.gotmpl @@ -31,9 +31,16 @@ run with -D adds no role for the fixture of content/canary.md. The path segment is the label through urlize, "Permanent Committee" - to permanent-committee and "Former Management Board (2018 - 2025)" to - former-management-board-2018-2025, under one directory, role/, so a - segment can never collide with a person id, which is firstname-surname. + to permanent-committee and "Mentor" to mentor, under one directory, + role/, so a segment can never collide with a person id, which is + firstname-surname. Three labels keep the segment of the words they + replaced (the table $segments below): the board is "Board (2026)" and + "Former Board (2018 - 2025)" since the glossary of 2026-10-25 and was + "Management Board" before, and the people who organized an event are + "Event organizer" and were "Organizer". Their pages stay at + management-board-2026, former-management-board-2018-2025, and + organizer, because a published release links the first one and + nothing is gained by moving the others. The page carries the label as params.filter, which is how every walker of the people section tells a listing from a person (a person has an id, a listing has a filter), and how layouts/people/role.html knows @@ -49,20 +56,25 @@ format; the name here is the path of the file under content/, which is unique, where two sections both hold a job-offers.md. - One more page, Assistants, which no label gives: /people/role/assistants/ + One more page, Attendees, which no label gives: /people/role/attendees/ answers the question a reader of the other tabs asks next, who came, and the answer is that the association never recorded it. The tab - exists to say so. It is the data policy of the - archive told as a joke: a programme, a board page, or a credit names + exists to say so. It was /people/role/assistants/ until the glossary + of 2026-10-25 (an assistant is a helper in English, the word was a + calque of the Catalan assistent), and the old address is an alias. It is the data policy of the + archive told as a joke: a program, a board page, or a credit names the people who spoke, organized, mentored, or collaborated, and an - attendee is on no such list. The one figure that exists is the count - of Meetup RSVPs, which the page of a meetup prints as registrations - and never as attendance (AGENTS.md: RSVPs are not attendance). The - page carries its text as content and the same filter param as the - others, so partials/people_tabs.html lists it from the pages like any - other view, with no count because there is no number to print, and - layouts/people/role.html prints the text where /people/ prints its - intro and no empty bar of letters under it. + attendee is on no such list. The one figure that exists is the sum + of the Meetup RSVPs, which the page of a meetup prints as RSVPs and + never as attendance (AGENTS.md: RSVPs are not attendance), and the + page prints that sum and says what it is. The text is not here: an + adapter runs before the pages exist and cannot add the figure up, so + the page carries the same filter param as the others and no content, + partials/people_tabs.html lists it from the pages like any other + view, with no count because it holds no people, and + layouts/people/role.html prints partials/attendees_note.html where + /people/ prints its intro and no empty bar of letters under it. The + Meetup RSVPs tile of the home page leads here with the same sum. */ -}} {{- $root := "content" -}} @@ -121,21 +133,30 @@ {{- end -}} {{- end -}} +{{- /* The labels whose page keeps the path segment of the words they + replaced. See the header. */ -}} +{{- $segments := dict + "Board (2026)" "management-board-2026" + "Former Board (2018 - 2025)" "former-management-board-2018-2025" + "Event organizer" "organizer" -}} + {{- /* The page of each label, in the order of the labels, so two builds add the pages in one order. The title is the label itself, the - words the row of a person prints and the tab reads. */ -}} + words the row of a person prints, and the tab reads the title. */ -}} {{- range $label, $_ := $labels -}} - {{- /* "Organizers (23)" and not "Organizer (23)": the heading names + {{- /* "Speakers (356)" and not "Speaker (356)": the heading names what the page holds, which is people. A label that is a group - and not a role ("Permanent Committee", "Management Board - (2026)") is already the name of the thing and is left alone. */ -}} + and not a role ("Permanent Committee", "Board (2026)") is + already the name of the thing and is left alone; the test is + a parenthesis or the word Committee, because a role can be two + words ("Event organizer", whose page is "Event organizers"). */ -}} {{- $title := $label -}} - {{- if not (or (strings.Contains $label " ") (strings.Contains $label "(")) -}} + {{- if not (or (strings.Contains $label "Committee") (strings.Contains $label "(")) -}} {{- $title = pluralize $label -}} {{- end -}} {{- $.AddPage (dict "kind" "page" - "path" (printf "role/%s" (urlize $label)) + "path" (printf "role/%s" (default (urlize $label) (index $segments $label))) "title" $title "layout" "role" "params" (dict @@ -143,15 +164,12 @@ "description" (printf "Every person the archive credits as %s, with their roles, their events, and their links." $label))) -}} {{- end -}} -{{- $assistants := `## We don't track that! - -The association has never recorded who came to an event. The archive holds the people who spoke, organized, mentored, or collaborated, because a programme, a board page, or a credit names them, and an attendee is on no such list. The one figure that exists is how many people said yes on Meetup, which the page of a meetup prints as registrations: a promise to come, not a seat filled.` -}} {{- $.AddPage (dict "kind" "page" - "path" "role/assistants" - "title" "Assistants" + "path" "role/attendees" + "title" "Attendees" "layout" "role" - "content" (dict "mediaType" "text/markdown" "value" $assistants) + "aliases" (slice "/people/role/assistants/") "params" (dict - "filter" "Assistants" - "description" "Who came to an event. The association never recorded it, so the archive holds the people who spoke, organized, mentored, or collaborated, and nobody else.")) -}} + "filter" "Attendees" + "description" "Who came to an event. The association never recorded it, so the archive holds the people who spoke, organized, mentored, or collaborated, and nobody else. The one figure is the Meetup RSVPs.")) -}} diff --git a/content/people/_index.md b/content/people/_index.md index 05ae3bad6..d9f6c01d5 100644 --- a/content/people/_index.md +++ b/content/people/_index.md @@ -5,4 +5,4 @@ menu: "main" weight: 3 --- -Everyone the archive credits, by name. A row holds the roles the person has held, how many events credit them, and the pages that say so: the programme of a day, its photos, and the page of the board or the committee they sat on. The tabs above the list keep one role at a time. The board, the committee, and the collaborators of today are grouped on [the organizers page](/pybcn_association/organizers/). +Everyone the archive credits, by name. A row holds the roles the person has held, how many events credit them, and the pages that say so: the program of a day, its photos, and the page of the board or the committee they sat on. The tabs above the list keep one role at a time. The board, the committee, and the collaborators of today are grouped on the [Who we are](/pybcn_association/organizers/) page. diff --git a/content/pybcn_association/collaborate.md b/content/pybcn_association/collaborate.md index 4e2d32d88..862f3eb17 100644 --- a/content/pybcn_association/collaborate.md +++ b/content/pybcn_association/collaborate.md @@ -11,13 +11,13 @@ heroBackground: /images/photos/people-pyday-2019.jpg --- -PyBCN runs on volunteers. Everything you see here, the monthly meetups, PyDay BCN, PyDataBCN, the PyLadies BCN workshops, is organised by people in the community who decided to help. +PyBCN runs on volunteers. Everything you see here, the monthly meetups, PyDay BCN, PyDataBCN, the PyLadies BCN workshops, is organized by people in the community who decided to help. There are several ways in, and none of them asks for much to start: * **[Become a member](/pybcn_association/membership/)** and support the association. * **[Give a talk](/pybcn_association/propose-a-talk/)** at a meetup. First talks are very welcome, and we will help you prepare it. -* **[Help organise an event](/pybcn_association/organize-with-us/)**, or propose one of your own. +* **[Help organize an event](/pybcn_association/organize-with-us/)**, or propose one of your own. * **[Sponsor us](/pybcn_association/sponsor-us/)**, or offer your office as a venue for a meetup. * **[Post a job offer](/pybcn_association/job-offers/)** to the community. * **[Promote your event](/pybcn_association/promote-your-event/)** if it is relevant to Python people in Barcelona. diff --git a/content/pybcn_association/information.md b/content/pybcn_association/information.md index 33d4f366b..d4f72b5e9 100644 --- a/content/pybcn_association/information.md +++ b/content/pybcn_association/information.md @@ -11,7 +11,7 @@ heroBackground: /images/photos/group-pydata-2017.jpg --- -After 10 years of experience organizing python-related events and more than 3000 members on Meetup, **Python Barcelona (PyBCN)** was officially registered as a non-profit association in 2018. PyBCN is a meeting point for all the Barcelona Python community, and we organize different monthly activities like [PyBCN and PyLadiesBCN meetups and practice sessions](../../events/monthly_events), along with some annual events like [PyDay BCN](../../events/pyday_bcn/pyday_bcn_2022) or [PyDataBCN](../../events/pydatabcn/pydatabcn_2023/). +After 10 years of experience organizing python-related events and more than 3000 people in its Meetup group, **Python Barcelona (PyBCN)** was officially registered as a non-profit association in 2018. PyBCN is a meeting point for all the Barcelona Python community, and we organize different monthly activities like [PyBCN and PyLadiesBCN meetups and practice sessions](../../events/monthly_events), along with some annual events like [PyDay BCN](../../events/pyday_bcn/pyday_bcn_2022) or [PyDataBCN](../../events/pydatabcn/pydatabcn_2023/). Would you like to be a part of PyBCN? We are looking forward to hearing from you! @@ -23,9 +23,9 @@ Would you like to be a part of PyBCN? We are looking forward to hearing from you ## How does PyBCN operate? -We have a Management Board and a Permanent Committee to make decisions, and work groups to drive all the association activity. +We have a Board and a Permanent Committee to make decisions, and work groups to drive all the association activity. -* **Management Board** +* **Board** * President: Jordi Bosch Alibau * Secretary: Daniel Mesejo Leon * Treasurer: Yago Tafalla @@ -46,7 +46,7 @@ We have a Management Board and a Permanent Committee to make decisions, and work All the work groups must follow some rules: * Every work group must have Chair, who will be accountable for the work group work to the Permanent Committee. - * The Chair is chosen by the work group members, who must be member of the Permanent Committee. + * The Chair is chosen by the people in the work group, who must sit on the Permanent Committee. * At least two members of the Permanent Committee must be part of every work group. * Nobody can participate in more than three work groups. * There's no other requirement to be a member of any work group. @@ -65,8 +65,8 @@ photograph of the day where the association published one. {{< assemblies >}} -## Past Management Boards -* Management Board 2018 - 2025 +## Past Boards +* Board 2018 - 2025 * President: Laura Pérez-Mayos * Secretary: Natàlia Padilla * Treasurer: Mireia Álvarez diff --git a/content/pybcn_association/legal-notice.md b/content/pybcn_association/legal-notice.md index f0eda4875..8b346f6a7 100644 --- a/content/pybcn_association/legal-notice.md +++ b/content/pybcn_association/legal-notice.md @@ -13,17 +13,17 @@ heroBackground: /images/photos/reg-desk-pyday-2019.jpg --- -This website, [pybcn.org](https://pybcn.org), is run by **Associació Python Barcelona** (PyBCN), a non-profit association of volunteers who organise Python meetups and events in Barcelona. +This website, [pybcn.org](https://pybcn.org), is run by **Associació Python Barcelona** (PyBCN), a non-profit association of volunteers who organize Python meetups and events in Barcelona. ## Who we are {{< association-identity >}} -The Management Board is responsible for this website. You can see who sits on it on the [Information](/pybcn_association/information/) page. +The Board is responsible for this website. You can see who sits on it on the [Information](/pybcn_association/information/) page. ## What this site is -This is an informational site. It describes the association, its events, the people who organise them and speak at them, and how to join, propose a talk, or sponsor us. Nothing is sold through this site. The membership fee is paid on PayPal's own site, not here. Some pages embed a Google Form or a Google Calendar, and the page of a recorded talk, the page of a recorded session, the page of a speaker, and the home page embed video in a YouTube player (youtube-nocookie.com); those frames are served by Google. +This is an informational site. It describes the association, its events, the people who organize them and speak at them, and how to join, propose a talk, or sponsor us. Nothing is sold through this site. The membership fee is paid on PayPal's own site, not here. Some pages embed a Google Form or a Google Calendar, and the page of a recorded talk, the page of a recorded session, the page of a speaker, and the home page embed video in a YouTube player (youtube-nocookie.com); those frames are served by Google. The site is a set of static pages, published from a public repository on GitHub and served by GitHub Pages. We keep no server of our own and we run no analytics. The [Privacy policy](/pybcn_association/privacy-policy/) says what personal data this involves. @@ -31,8 +31,8 @@ The site is a set of static pages, published from a public repository on GitHub - The text on this site is written by volunteers and belongs to the association. You can quote it with a link to the page. Ask us before you reuse more than that. - The photographs and biographies on the people pages belong to the people shown. Do not reuse them without their permission. -- The logos of sponsors and partner organisations belong to their owners. -- The site code is in a [public repository](https://github.com/pybcn/pybcn.github.io) on GitHub. The theme is free software under the MIT licence. +- The logos of sponsors and partner organizations belong to their owners. +- The site code is in a [public repository](https://github.com/pybcn/pybcn.github.io) on GitHub. The theme is free software under the MIT license. ## Links to other sites @@ -54,4 +54,4 @@ We may update this notice. Every change is visible in the [history of this page] Spanish law applies to this notice and to the use of this site. Any dispute goes to the courts of Barcelona, unless the law gives you the right to the courts of your own domicile. -Last updated: 2026-10-14 +Last updated: 2026-10-25 diff --git a/content/pybcn_association/membership.md b/content/pybcn_association/membership.md index 41677f194..760dddacb 100644 --- a/content/pybcn_association/membership.md +++ b/content/pybcn_association/membership.md @@ -11,7 +11,7 @@ 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!** +The Python Barcelona Association, a.k.a. PyBCN, is a non-profit organization 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!** {{< grid-row >}} {{< grid-col md="6" >}} diff --git a/content/pybcn_association/organizers.md b/content/pybcn_association/organizers.md index b636826dc..5d174909c 100644 --- a/content/pybcn_association/organizers.md +++ b/content/pybcn_association/organizers.md @@ -1,5 +1,5 @@ --- -title: "Organizers" +title: "Who we are" # The name the appearance list of a person modal calls this page by. The # line there reads "Permanent Committee at PyBCN", where the title would # read "Permanent Committee at Organizers" and repeat the role. See @@ -17,7 +17,7 @@ heroBackground: /images/photos/reg-desk-pyday-2019.jpg people_levels: - people_per_line: 5 people: [jordi-bosch, daniel-mesejo-leon, yago-tafalla, mauricio-volcanes, sergi-ramirez] - name: Management Board (2026) + name: Board (2026) # The faces the home page shows, which are the two bodies that # run the association. home_faces: true @@ -31,7 +31,7 @@ people_levels: people: [elisabeth-ortega-carrasco, josep-martinez-vila, loris-mularoni, laura-perez-mayos, nuria-pujol-vilanova, jose-riera-sanchez, ruben-berenguel, xavi-francisco-gilabert] name: Collaborators - people_per_line: 5 - name: Former Management Board (2018 - 2025) + name: Former Board (2018 - 2025) # An entry with a role shows that role on this page instead of the # pybcn_position of the person file. See people-grid.html. people: diff --git a/content/pybcn_association/privacy-policy.md b/content/pybcn_association/privacy-policy.md index d77b5b1be..034e797c2 100644 --- a/content/pybcn_association/privacy-policy.md +++ b/content/pybcn_association/privacy-policy.md @@ -22,19 +22,27 @@ PyBCN is a volunteer association. This page says what personal data this website - **Email**: [pybcn@googlegroups.com](mailto:pybcn@googlegroups.com) - **Registered address**: Carrer de Concepció Arenal, 165, 08027 Barcelona -The Management Board handles requests about personal data. We have no data protection officer: the law does not require one for an association of our size and activity. +The Board handles requests about personal data. We have no data protection officer: the law does not require one for an association of our size and activity. ## What data this site involves, and why ### People pages -The site has pages for the people who organise our events, speak at them, mentor at workshops, or collaborate with the association. Each page shows a name, a photograph, a short biography, the role in PyBCN or at an event, and links to the person's own profiles (GitHub, LinkedIn, Twitter, personal site). +The site has pages for the people who organize our events, speak at them, mentor at workshops, or collaborate with the association. Each page shows a name, a photograph, a short biography, the role in PyBCN or at an event, and links to the person's own profiles (GitHub, LinkedIn, Twitter, personal site). -- **Where it comes from**: the person. Each one sent the photograph and wrote or approved the text for publication here. Someone who did not want a photograph did not send one, and the page shows a silhouette instead. -- **Why we have it**: with the person's consent (GDPR article 6.1.a). You can withdraw it at any time, and we remove the page. Withdrawing consent does not affect what was published before. +- **Where it comes from**: for most people, the person. They sent the photograph and wrote or approved the text for publication here. For speakers that the archive credits, the public announcements of our own Meetup events: the page then shows the name, the talks, and the events. A page with no photograph shows the initials of the name on a color instead; the grid of organizers or speakers on an event page shows a silhouette. +- **Why we have it**: for a page that the person sent, their consent (GDPR article 6.1.a). You can withdraw it at any time, and we remove the page. Withdrawing consent does not affect what was published before. For a page built from our announcements, our legitimate interest in keeping the history of the community (GDPR article 6.1.f). You can object to it, and we remove the page (see [Your rights](#your-rights)). - **How long we keep it**: until the person asks us to remove it, or until we take the page down ourselves because it is out of date. - **One thing to know**: the source of this site is a public Git repository on GitHub. When we remove a page, it disappears from the site and from the current version of the repository. The old text remains in the repository history, as with any Git project. Tell us if you also want it gone from there and we will work it out with you. Copies kept by search engines and web archives are outside our control. +### Event photographs + +Some event pages show photographs from the posts of the association on X, with the caption they were posted with. Only photographs that the association published itself are on the site. They show the event in general: a speaker gave the talk in public and accepted that it was recorded, and the audience appears in the background and from a distance. + +- **Where it comes from**: the public posts of the association on X. +- **Why we have it**: our legitimate interest in keeping the history of the community (GDPR article 6.1.f). You can object to a photograph in which you appear, and we remove it (see [Your rights](#your-rights)). +- **How long we keep it**: until someone objects to it, or until we remove the gallery. + ### Forms A few pages link to or embed a Google Form: @@ -49,7 +57,7 @@ Each form asks for what it needs to handle your request: usually your name, an e - **Where it goes**: into a Google Forms spreadsheet in a Google account run by the association's organizers. Google stores it under its own [privacy policy](https://policies.google.com/privacy). - **Why we have it**: to do what you asked for, which is the membership agreement or the steps you take to propose a talk or join a workshop (GDPR article 6.1.b). - **Who sees it**: the organizers of that event or working group. -- **How long we keep it**: responses to an event form are needed until the event is over and its programme is published. We have no automatic deletion after that. Ask us and we delete your response. Membership data stays in the member register for as long as you are a member; the law requires associations to keep that register and the related accounting records for some years after. +- **How long we keep it**: responses to an event form are needed until the event is over and its program is published. We have no automatic deletion after that. Ask us and we delete your response. Membership data stays in the member register for as long as you are a member; the law requires associations to keep that register and the related accounting records for some years after. ### Membership payments @@ -57,13 +65,13 @@ The membership fee is paid on [PayPal](https://www.paypal.com)'s site through a ### Email -Our contact addresses, such as pybcn@googlegroups.com and pyladies-bcn@googlegroups.com, are Google Groups. A message you send there is stored in the group and read by the organizers who are members of that group. We use it to answer you and to follow up on what you asked (GDPR article 6.1.b and 6.1.f). The thread stays in the group archive; ask us and we delete it. +Our contact addresses, such as pybcn@googlegroups.com and pyladies-bcn@googlegroups.com, are Google Groups. A message you send there is stored in the group and read by the organizers who belong to that group. We use it to answer you and to follow up on what you asked (GDPR article 6.1.b and 6.1.f). The thread stays in the group archive; ask us and we delete it. ### Embedded Google content A few pages embed a Google Form or a Google Calendar in a frame: the two talk proposal forms and the agenda of PyDay BCN 2019. The frame is served by Google: when the page loads, Google sees your IP address and browser details, and may set its own cookies inside the frame. Google's [privacy policy](https://policies.google.com/privacy) applies to that. -Some pages embed a video in a frame from **youtube-nocookie.com**, the YouTube player Google serves for sites that do not want it to set cookies. Four kinds of page carry one: the page of a talk that was recorded, one frame per talk; the page of a meetup whose session was recorded as a whole, one frame per recording; the page of a person, one frame per recorded talk they gave; and the home page, which plays the presentation of the Barcelona community at PyConES 2020. No other page has one: the lists of events, talks, and people, and the programme of an event, carry a link to the video and nothing else. What the frame does and does not do: +Some pages embed a video in a frame from **youtube-nocookie.com**, the YouTube player Google serves for sites that do not want it to set cookies. Four kinds of page carry one: the page of a talk that was recorded, one frame per talk; the page of a meetup whose session was recorded as a whole, one frame per recording; the page of a person, one frame per recorded talk they gave; and the home page, which plays the presentation of the Barcelona community at PyConES 2020. No other page has one: the lists of events, talks, and people, and the program of an event, carry a link to the video and nothing else. What the frame does and does not do: - When you open one of those pages and scroll near a video, your browser asks Google for the player. Google then sees your IP address and browser details, and that you opened that page on this site, as it would for an image loaded from its servers. This happens before you press play. - Until you press play, Google states that this player stores nothing in your browser and sets no cookie. @@ -72,7 +80,7 @@ Some pages embed a video in a frame from **youtube-nocookie.com**, the YouTube p ### Cookies -This site sets no cookies of its own, and runs no analytics or tracking scripts. Your browser also loads a few images from unsplash.com (page headers) and paypalobjects.com (the PayPal button). Like any image host, those servers see your IP address and browser details. +This site sets no cookies of its own, and runs no analytics or tracking scripts. Its scripts, styles, fonts, and images are served from this site, with two exceptions: the membership pages load the PayPal button from paypalobjects.com, and the page of PyDay BCN 2018 loads the Eventbrite ticket button from eventbrite.es. Like any image host, those servers see your IP address and browser details. ### Hosting @@ -80,7 +88,7 @@ The site is served by [GitHub Pages](https://pages.github.com). GitHub may log t ## Who else sees your data -Nobody buys or receives your data from us. The companies named above see it because we use their services: Google (forms, calendar, mailing lists, documents, and the YouTube player on the talk pages), PayPal (payments), and GitHub (hosting and the source repository). All three are based in the USA. Each publishes the safeguards it applies to data from the EU, and we rely on those. +Nobody buys or receives your data from us. The companies named above see it because we use their services: Google (forms, calendar, mailing lists, documents, and the YouTube player on the talk pages), PayPal (payments), Eventbrite (the ticket button on the page of PyDay BCN 2018), and GitHub (hosting and the source repository). All four are based in the USA. Each publishes the safeguards it applies to data from the EU, and we rely on those. ## Your rights @@ -101,4 +109,4 @@ If you think we handle your data wrongly, you can complain to the Spanish data p We may update this policy. Every change is visible in the [history of this page](https://github.com/pybcn/pybcn.github.io/commits/edition/content/pybcn_association/privacy-policy.md) on GitHub. -Last updated: 2026-10-14 +Last updated: 2026-10-25 diff --git a/content/pybcn_association/promote-your-event.md b/content/pybcn_association/promote-your-event.md index 8cfeea36d..a807b0578 100644 --- a/content/pybcn_association/promote-your-event.md +++ b/content/pybcn_association/promote-your-event.md @@ -19,8 +19,8 @@ heroBackground: /images/photos/reg-desk-pyday-2019.jpg - It must be clearly stated **who is organizing the event**, and therefore who is responsible for it. ## What do you get -- We'll forward your event information to our PyBCN meetup list, with more than 3K members. -- We'll forward your event information to our PyLadiesBCN meetup list, with more than 600 members. +- We'll forward your event information to our PyBCN Meetup group, with more than 3K people. +- We'll forward your event information to our PyLadiesBCN Meetup group, with more than 600 people. - We'll mention your event in our social networks. ## How does it work? diff --git a/content/pyladies_bcn/_index.md b/content/pyladies_bcn/_index.md index 60f5cb68e..2458fedc5 100644 --- a/content/pyladies_bcn/_index.md +++ b/content/pyladies_bcn/_index.md @@ -13,7 +13,7 @@ config: "pyladies_first" **[About PyLadiesBCN!](/pyladies_bcn/about)**\ Learn all about our mission -**[Organisers and speakers!](/pyladies_bcn/organizers-and-speakers)**\ +**[Organizers and speakers!](/pyladies_bcn/organizers-and-speakers)**\ The people that make it possible **[Upcoming meetups!](/pyladies_bcn/meetups)**\ diff --git a/content/pyladies_bcn/about.md b/content/pyladies_bcn/about.md index 024f3ff44..58928ecd7 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](https://www.pyladies.com). +And if you'd like to get some more information about our parent organization, check out [their website](https://www.pyladies.com). All our events adhere to a strong [Code of Conduct](/pybcn_association/coc/). diff --git a/content/talks/_content.gotmpl b/content/talks/_content.gotmpl index 811641d0a..227bfdac9 100644 --- a/content/talks/_content.gotmpl +++ b/content/talks/_content.gotmpl @@ -1,5 +1,5 @@ {{- /* - One page per talk, built from the programme of every event. + One page per talk, built from the program of every event. The talks of this archive live in the front matter of the event that gave them, under the talks block, and that is where they stay: a talk @@ -20,7 +20,7 @@ partials/talk_record.html, which reads the talk out of the event page through site.GetPage. So the description, the speakers, the language, the links, and the photo have one source, the event front matter, and - cannot drift from what the programme grid and the gallery of that day + cannot drift from what the program grid and the gallery of that day print. Why the event is part of the path. A talk id is unique inside its @@ -100,7 +100,7 @@ {{- /* The files to read: the markdown of content/events/ and of each series under it. An _index.md is the container of a section and carries no - programme of its own. */ -}} + program of its own. */ -}} {{- $files := slice -}} {{- range $entry := os.ReadDir $root -}} {{- $here := path.Join $root $entry.Name -}} @@ -135,7 +135,7 @@ {{- $slug := path.BaseName $file -}} {{- /* The date of the event is the date of every talk of it. One edition of the section carries no date, Hacktoberfest 2018, - and it carries no talks either; a programme with no date + and it carries no talks either; a program with no date would still get its pages, dated by the build. */ -}} {{- $dates := dict -}} {{- with $event.date -}} diff --git a/content/talks/_index.md b/content/talks/_index.md index 0a255dbdd..72f1ce8cb 100644 --- a/content/talks/_index.md +++ b/content/talks/_index.md @@ -5,4 +5,4 @@ menu: "main" weight: 6 --- -Every talk the association has put on a programme, newest first. Each one has a page of its own with its speakers, the day it was given, its description, its photo, and whatever the speaker published: the video, the slides, and the code. +Every talk the association has put on a program, newest first. Each one has a page of its own with its speakers, the day it was given, its description, its photo, and whatever the speaker published: the video, the slides, and the code. diff --git a/data/event_emoji.yaml b/data/event_emoji.yaml index f91b4b6f7..4d1b41b00 100644 --- a/data/event_emoji.yaml +++ b/data/event_emoji.yaml @@ -20,7 +20,7 @@ # 2. The group. A page whose front matter carries group: "PyLadies BCN" # is a pyladies, whatever its title says: a PyLadies dojo shows the # PyLadies marker and not the dojo one, because the community that -# organised it is the more distinctive fact. +# organized it is the more distinctive fact. # 3. The kind, from a word of the title: dojo, practice session, # barbecue, hacktoberfest or hackathon (one kind), sprint, # coderetreat, and workshop last. Three titles carry two of those @@ -49,7 +49,7 @@ # community, and the glyph says so next to 👥. A martial arts uniform for # a coding dojo, which is a kata in the sense the word came with. Books # for a practice session, a laptop for a workshop (the icon the workshop -# talks of a programme carry already, fa-laptop), meat on a bone for a +# talks of a program carry already, fa-laptop), meat on a bone for a # barbecue, a wrench for a hackathon, a runner for a sprint, and a person # in lotus position for a coderetreat, which is a day of retreat. # diff --git a/data/role_emoji.yaml b/data/role_emoji.yaml index fa6470fe0..f38f49393 100644 --- a/data/role_emoji.yaml +++ b/data/role_emoji.yaml @@ -4,7 +4,7 @@ # of the event page through roles.yaml. For a roles row it is the label of # the row, which is a level name of an organizers page through roles.yaml, # and a level name that is not a role ("Permanent Committee", -# "Management Board (2026)") is not here and takes the "*" entry. Right side: one emoji. A role that is not here takes the "*" +# "Board (2026)") is not here and takes the "*" entry. Right side: one emoji. A role that is not here takes the "*" # entry, so a new role shows up with a neutral glyph rather than with # none, and the row does not change shape when it is added. The three # level names above are the live test of that fallback. @@ -25,7 +25,7 @@ Speaker: 🎤 Mentor: 🎓 Volunteer: 🙋 -Organizer: 🧭 +Event organizer: 🧭 Collaborator: 🤝 President: 🔑 Former President: 🔑 @@ -45,12 +45,12 @@ Events: 📅 # needs a row of its own, and until it has one its glyph is the neutral # one, not a wrong one. Permanent Committee: 🧭 -Management Board (2026): 📋 -Former Management Board (2018 - 2025): 📋 +Board (2026): 📋 +Former Board (2018 - 2025): 📋 # Not a role and not a level: the tab of /people/ that answers "who came" # with the fact that the association never recorded it (see # content/people/_content.gotmpl). An empty chair, for the audience the # archive has no list of. U+1FA91 has emoji presentation by default, as # the rule above asks. -Assistants: 🪑 +Attendees: 🪑 diff --git a/data/roles.yaml b/data/roles.yaml index 953976663..be584d6fd 100644 --- a/data/roles.yaml +++ b/data/roles.yaml @@ -19,8 +19,8 @@ # 2016. Unmapped, it printed "Collaborators at PyBCN" on the page of one # person, a plural for one. Speakers: Speaker -Organizers: Organizer +Organizers: Event organizer Collaborators: Collaborator Mentors: Mentor Volunteers: Volunteer -PyLadiesBCN Organizers: Organizer +PyLadiesBCN Organizers: Event organizer diff --git a/layouts/_default/_markup/render-link.html b/layouts/_default/_markup/render-link.html index 6b476d5a2..55ecb22a4 100644 --- a/layouts/_default/_markup/render-link.html +++ b/layouts/_default/_markup/render-link.html @@ -3,9 +3,9 @@ Content used to write raw to open an external site in a new tab. Those were converted to plain markdown links, - so the behaviour has to come from here. The raw ones would still render, + so the behavior has to come from here. The raw ones would still render, because unsafe=true is set in [markup.goldmark.renderer] in config.toml - for the two pre-Hugo programmes pasted in as tables, but no new content + for the two pre-Hugo programs pasted in as tables, but no new content writes an anchor of its own. An external link gets target="_blank" and rel="noopener noreferrer". @@ -13,7 +13,7 @@ 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. + keep the default behavior and open in the same tab. */ -}} {{- $url := urls.Parse .Destination -}} {{- $external := and $url.Host (ne $url.Host (urls.Parse .Page.Site.BaseURL).Host) -}} diff --git a/layouts/_default/rss.xml b/layouts/_default/rss.xml index 1299c8609..3e52fcdf6 100644 --- a/layouts/_default/rss.xml +++ b/layouts/_default/rss.xml @@ -49,7 +49,7 @@ feed. They are in the sitemap, where a page of the site belongs. */ -}} {{- $pages = where $pages "Section" "ne" "people" }} {{- /* The talk pages are not in the feed. There is one per talk of every - programme the association has published (bin/check-content prints the + program the association has published (bin/check-content prints the count), and they are built from the front matter of the events, which the feed already carries (see content/talks/_content.gotmpl). None of them is a publication: the date of a talk is the day it was given, as diff --git a/layouts/partials/friends.html b/layouts/partials/friends.html index ab4fb46aa..21158e48a 100644 --- a/layouts/partials/friends.html +++ b/layouts/partials/friends.html @@ -12,7 +12,7 @@ publish no favicon at all: bcneng.org and pythongirona.cat answer 404 on every usual path and declare no icon link, so what is kept here is the logo each one - draws on its own page, which is the mark a reader recognises anyway. + draws on its own page, which is the mark a reader recognizes anyway. Python España does publish one, and that is the file used. The file is in this repository and is never fetched from the other diff --git a/layouts/shortcodes/association-identity.html b/layouts/shortcodes/association-identity.html index 70db41d91..93af1354a 100644 --- a/layouts/shortcodes/association-identity.html +++ b/layouts/shortcodes/association-identity.html @@ -23,7 +23,7 @@

    diff --git a/layouts/shortcodes/logo-row.html b/layouts/shortcodes/logo-row.html index 624a440ce..2dd2e8026 100644 --- a/layouts/shortcodes/logo-row.html +++ b/layouts/shortcodes/logo-row.html @@ -1,5 +1,5 @@ {{- /* - logo-row: a centred row of sponsor logos. + logo-row: a centered row of sponsor logos. Usage: {{< logo-row >}} diff --git a/static/humans.txt b/static/humans.txt index f0cb76cb0..13986e94f 100644 --- a/static/humans.txt +++ b/static/humans.txt @@ -61,4 +61,10 @@ Search Pagefind, https://pybcn.org/search/ The index is built with the site and served from it: searching asks nobody else Language English - Privacy No page asks another site for anything to draw itself + Privacy Scripts, styles, fonts, and images are served from this site. + A page asks another site only for the YouTube player of a + recorded talk, the Google Form of the talk proposals, the + Google Calendar of PyDay BCN 2019, the PayPal button of the + membership page, and the Eventbrite button of PyDay BCN 2018. + The whole list: + https://pybcn.org/pybcn_association/privacy-policy/ diff --git a/themes/pybcn_theme/assets/scss/agenda.scss b/themes/pybcn_theme/assets/scss/agenda.scss index 3a6e0f76b..fe96afb78 100644 --- a/themes/pybcn_theme/assets/scss/agenda.scss +++ b/themes/pybcn_theme/assets/scss/agenda.scss @@ -75,9 +75,9 @@ $blockTimes15: 700,715,730,745,800,815,830,845,900,915,930,945,1000,1015,1030,10 // rather than push the grid wider than the screen. Issue #212. overflow-wrap: break-word; /* - The fallback for an entry with no colour class. White text on + The fallback for an entry with no color class. White text on the CSS orange was 1.97:1. #A15C00 is 5.19:1 on white, so an - entry that omits its colour stays readable. bin/check-content + entry that omits its color stays readable. bin/check-content reports such an entry, so nothing should reach this fallback. */ background-color: #A15C00; @@ -105,8 +105,8 @@ $blockTimes15: 700,715,730,745,800,815,830,845,900,915,930,945,1000,1015,1030,10 /* The title of a row that holds a talk goes to the page of that talk. Underlined, so it reads as a link before the pointer - reaches it: colour alone cannot say it here, because the whole - block is one colour and the title takes the same white or dark + reaches it: color alone cannot say it here, because the whole + block is one color and the title takes the same white or dark text as the rest of it. WCAG 1.4.1 asks for a second mark, and the underline is the mark a link takes everywhere else on this site (see .photo_source in photo_gallery.scss). @@ -157,7 +157,7 @@ $blockTimes15: 700,715,730,745,800,815,830,845,900,915,930,945,1000,1015,1030,10 text and so needs 4.5:1 against its background. White on the old yellow was 1.81:1 and on the old orange 2.63:1. - Yellow and orange keep their brand colour and take dark text + Yellow and orange keep their brand color and take dark text instead, which reads better than any darkened version would: 8.51:1 and 5.87:1. Blue and pink work with neither white nor dark text as they were, so they are darkened just enough for white to @@ -264,13 +264,13 @@ $blockTimes15: 700,715,730,745,800,815,830,845,900,915,930,945,1000,1015,1030,10 * 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 + * on the color 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. + * cell color, 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%. diff --git a/themes/pybcn_theme/assets/scss/facts.scss b/themes/pybcn_theme/assets/scss/facts.scss index 788ba9797..ca2be1136 100644 --- a/themes/pybcn_theme/assets/scss/facts.scss +++ b/themes/pybcn_theme/assets/scss/facts.scss @@ -7,7 +7,7 @@ // div, so a row is one element in the markup, and the div is display: // contents so its dt and dd take the two cells of a row of the grid. The box // is the bordered pill of .count_card (main.scss) at full width, in the -// colour of the facts, so the two read as one kind of thing: a box of +// color of the facts, so the two read as one kind of thing: a box of // figures. At 390px the two columns still fit, because the longest label // takes about a third of the width and a long value wraps inside its cell. .facts_box { @@ -47,7 +47,7 @@ overflow-wrap: anywhere; } - // A link inside the box needs a second mark besides the colour, which + // A link inside the box needs a second mark besides the color, which // is WCAG 1.4.1 and the rule this repository applies to .photo_source // and to the caption of a talk photo. The credit row holds text between // two links ("A and B"), which is where axe reports link-in-text-block. diff --git a/themes/pybcn_theme/assets/scss/footer.scss b/themes/pybcn_theme/assets/scss/footer.scss index a71233976..cca87fec2 100644 --- a/themes/pybcn_theme/assets/scss/footer.scss +++ b/themes/pybcn_theme/assets/scss/footer.scss @@ -48,7 +48,7 @@ footer { // 8. The footer in four columns, the sub-list of the pages that Take part // also links, the accounts on one line beside the name of the association, -// and the licence line. +// and the license line. .site_footer { .site_footer_col { margin-bottom: 1.5rem; @@ -103,7 +103,7 @@ footer { .site_licence { margin: 0.75rem 0 0; - // Centred: it is the line that closes the page and it belongs to + // Centered: it is the line that closes the page and it belongs to // the whole of it, not to the column it happens to sit under. text-align: center; color: rgba(255, 255, 255, 0.7); @@ -122,9 +122,9 @@ footer { } } - // The live footer centres everything under 576px. A vertical list + // The live footer centers everything under 576px. A vertical list // reads from a left edge, and so does its sub-list, so the columns - // stay left; the name and the accounts take the centre. + // stay left; the name and the accounts take the center. @media (max-width: 576px) { .site_footer_col { text-align: left; diff --git a/themes/pybcn_theme/assets/scss/home.scss b/themes/pybcn_theme/assets/scss/home.scss index de9fa1048..f27713bf1 100644 --- a/themes/pybcn_theme/assets/scss/home.scss +++ b/themes/pybcn_theme/assets/scss/home.scss @@ -16,11 +16,11 @@ // footer.scss and not here. // The blocks of this page come from three proposals with three type scales // and three spacings. What makes them one page is here: one h1, one h2 -// style for every section (.home_title) with a colour variant for a dark +// style for every section (.home_title) with a color variant for a dark // band, one card frame (.home_card) for the Meetup cards, the Take part // boxes, and the friends, with the same border, radius, and hover, and // one rhythm of 3rem between the sections. -// The colours and the figures of this design ($blue-deep, $rule-grey, +// The colors and the figures of this design ($blue-deep, $rule-grey, // $text-grey, $ink, $paper, $hover-blue, $card-radius, $block-gap, // $title-gap) are in main.scss since 2026-10-17, next to $blue-pybcn, // because every other page takes them from there now: the section title, @@ -122,20 +122,34 @@ grid-template-columns: repeat(2, 1fr); } + // Six tiles since the glossary of 2026-10-25 (they were four): + // two rows of three from 992px, where six on one row left + // "8,917 Meetup RSVPs" no room beside its glyph. @media (min-width: 992px) { - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(3, 1fr); gap: 1rem; } + + // Every row of tiles as tall as the tallest: the People tile + // carries a caption under its label, and without this its row + // was 16px taller than the row under it. + grid-auto-rows: 1fr; } .home_stat { display: flex; align-items: baseline; - // Centred in the tile. Left aligned, the four tiles of one row + // Centered in the tile. Left aligned, the four tiles of one row // put their numbers at four different distances from their own // left edge, because "281 Events" and "371 People" are not the // same width, and the row read as crooked. justify-content: center; + // Wrapping is on so that align-content applies, which is what + // centers the glyph, the number, and the label in a tile taller + // than they are (see grid-auto-rows above). Nothing wraps at + // the widths measured, 390 to 1440px. + flex-wrap: wrap; + align-content: center; gap: 0.6rem; height: 100%; padding: 0.75rem 1.25rem; @@ -163,6 +177,18 @@ font-size: 1.1rem; } + // The caption of the People tile, under its label, in the words + // the number counts. Smaller and allowed to wrap: the tile keeps + // nowrap for its number and its label, and a caption of four + // words would not fit beside them at 992px. + .home_stat_caption { + display: block; + font-size: 0.8rem; + line-height: 1.2; + white-space: normal; + opacity: 0.85; + } + &:hover, &:focus { border-color: $yellow-pybcn; @@ -194,7 +220,7 @@ // 2. About, on the dark band of option 3, right under the hero: the text // at the left, the player at the right. The links in the text take the -// yellow, the one colour that reads on the dark grey beside white. +// yellow, the one color that reads on the dark grey beside white. .home_story { padding: 2.5rem 0 3rem; background-color: $dark-grey; @@ -252,7 +278,7 @@ background-repeat: no-repeat; // Flush with the top edge of the card, not floating in the // middle of it: the two marks are drawn to sit on a line and - // centred they read as sliding down the card. + // centered they read as sliding down the card. background-position: left top; background-size: contain; } diff --git a/themes/pybcn_theme/assets/scss/listing_table.scss b/themes/pybcn_theme/assets/scss/listing_table.scss index f993f1591..bc211a1ab 100644 --- a/themes/pybcn_theme/assets/scss/listing_table.scss +++ b/themes/pybcn_theme/assets/scss/listing_table.scss @@ -34,7 +34,7 @@ margin-bottom: 2rem; border-collapse: collapse; - // The caption reads as a note about the table, in the colour and the + // The caption reads as a note about the table, in the color and the // size of the facts, above the header row where a reader looks first. .listing_caption { caption-side: top; @@ -93,7 +93,7 @@ // The marker of a talk: the icon of its type, in the box of the // event emoji above, so the titles of the two tables hang by the - // same 2.1rem. The icon is text, so it takes the colour of the facts. + // same 2.1rem. The icon is text, so it takes the color of the facts. .talk_marker { display: inline-block; width: 1.75rem; @@ -136,7 +136,7 @@ } } - // The event, in the weight of the month and the colour of the text: + // The event, in the weight of the month and the color of the text: // it is a group header, and it is a link. .talk_event_cell { font-weight: 600; @@ -147,7 +147,7 @@ white-space: nowrap; } - // The two header cells of a group, in the colour of the facts: they + // The two header cells of a group, in the color of the facts: they // are labels in a margin and not titles. .listing_year, .listing_month { diff --git a/themes/pybcn_theme/assets/scss/main.scss b/themes/pybcn_theme/assets/scss/main.scss index 67131464f..cb60ae787 100644 --- a/themes/pybcn_theme/assets/scss/main.scss +++ b/themes/pybcn_theme/assets/scss/main.scss @@ -8,7 +8,7 @@ $blue-pybcn: #006c9b; :root { color-scheme: only light; } -// The rest colour of an icon that lights up under the pointer: a social +// The rest color of an icon that lights up under the pointer: a social // glyph on a card and in a modal. 4.68:1 on white, above the 3:1 WCAG // 1.4.11 asks of a graphic that carries meaning. $icon-grey: #6c757d; @@ -174,7 +174,7 @@ $title-gap: 1.5rem; // Font Awesome 5.8.2 is older than the Twitter rename, so it carries no X // mark. This draws the mark from the Font Awesome 6 Free path (CC BY 4.0) as // a CSS mask, which keeps one vendored icon set instead of two. The mask takes -// its colour from `currentColor`, so the icon follows the same colour and +// its color from `currentColor`, so the icon follows the same color and // hover rules as every Font Awesome glyph next to it. .icon_x { display: inline-block; @@ -212,11 +212,11 @@ $title-gap: 1.5rem; // The mark of a link that leaves the site, printed by // partials/link_mark.html in front of the words of the link: the YouTube // mark, the GitHub mark, the X mark above, or the generic arrow. Grey at -// rest, the $icon-grey of every icon of the site, and the colour of the +// rest, the $icon-grey of every icon of the site, and the color of the // link under the pointer or the keyboard, which is the rule the social // glyphs of a person card follow. The YouTube mark took the blue of the // link around it until 2026-10-15 while every other icon was grey. They -// are one colour now. An inline-block, so the underline of the +// are one color now. An inline-block, so the underline of the // link stops at the words and is not drawn through the glyph. The gap is // the one the credit of a gallery photo and the video line of a talk row // already set. @@ -400,7 +400,7 @@ button:focus:not(:focus-visible), // The paragraph a page opens with, above the list or the cards it is the // index of: .section_intro on /events/, /people/, /talks/ and // /events/meetups/, .page-intro on the two monthly meetup pages. A link -// inside a sentence needs a second mark besides the colour, which is WCAG +// inside a sentence needs a second mark besides the color, which is WCAG // 1.4.1 and the rule this repository already applies to .photo_source and // to the caption of a talk photo. axe reported this one as // link-in-text-block on 7 links over 4 pages. @@ -494,7 +494,7 @@ button:focus:not(:focus-visible), text-align: center; } - // /people/ centres its letters; /events/ + // /people/ centers its letters; /events/ // keeps its years at the left, over the first column of its table. // The class is the optional argument of partials/jump_bar.html. &.jump_bar_centered ul { @@ -503,15 +503,16 @@ button:focus:not(:focus-visible), } // The tabs above a listing: one link per view of the list, the current -// one filled. See layouts/partials/filter_tabs.html, which /talks/ and -// /people/ draw it with, and which says why the tabs are links to pages -// and not a script. +// one filled. See layouts/partials/filter_tabs.html, which /talks/, +// /people/, and /events/ draw it with, and which says why the tabs are +// links to pages and not a script. // // The same pills as .jump_bar, a little taller, so the two bars read as // one family of controls: the tabs choose which rows the page holds, the // bar under them jumps inside those rows. The list wraps, with no script, -// as the jump bar does: at 390px the six tabs of /talks/ take three lines -// and the ten of /people/ four, and the document stays 390px wide. +// as the jump bar does: at 390px the six tabs of /talks/ take three lines, +// the ten of /people/ four, and the five of /events/ three, and the +// document stays 390px wide. // // The current tab is the one with aria-current, painted in the blue of the // site with white text, which is the one pair of this stylesheet that is @@ -573,7 +574,7 @@ button:focus:not(:focus-visible), } // The legend above a long index: each marker the rows draw, with how many -// rows carry it. One line that wraps, in the colour of the facts under a +// rows carry it. One line that wraps, in the color of the facts under a // row, so it reads as information about the list and not as a row of it. // See layouts/partials/marker_legend.html, which /events/ and /talks/ draw // it with. @@ -630,7 +631,7 @@ button:focus:not(:focus-visible), // The card of counts of a row: one icon and one number per kind of thing // the row holds. See layouts/partials/count_card.html, which the three -// listings of the archive print it with. A bordered pill in the colour of +// listings of the archive print it with. A bordered pill in the color of // the facts, with the border and the radius of a link of .jump_bar, so it // reads as a box of figures and not as a sentence. The items never wrap // inside the card: the card wraps as a whole, through .row_facts. diff --git a/themes/pybcn_theme/assets/scss/people.scss b/themes/pybcn_theme/assets/scss/people.scss index fdb546b26..e0ad73b20 100644 --- a/themes/pybcn_theme/assets/scss/people.scss +++ b/themes/pybcn_theme/assets/scss/people.scss @@ -25,8 +25,8 @@ // Every row of cards starts on the same left edge as the heading above // it, which is the line the eye follows down the page. Three rules are // needed. The row caps its own width further down, so it must not be - // centred in the column. The cards of a row that does not fill must not - // be centred under the cards above them. And the half gutter each card + // centered in the column. The cards of a row that does not fill must not + // be centered under the cards above them. And the half gutter each card // carries on its left has to come back off the row, so the edge of the // first card, not the edge of its gutter, is what lands on the line. .row.level { @@ -35,6 +35,13 @@ margin-right: -$gutter / 2; } + // A level heading is a link target (people-grid.html gives it an id + // from its name), so it clears the fixed navigation when a link + // lands on it, as the year headers of a listing do (listing_table.scss). + .level_name { + scroll-margin-top: 80px; + } + // Every card is the same width in every section, and so is the space // between them. The row caps its own width at the number of cards it is // asked for, and each slot is that fraction of the row. The cap is what @@ -134,10 +141,10 @@ // The photo, the name and the role are one link to the page of // the person (see people_summary.html). A block, so the two // boxes inside it stack as they did when each was a button. It - // keeps the colours of the card: the name is black at rest and + // keeps the colors of the card: the name is black at rest and // the PyBCN blue under the pointer or the keyboard, which the // rules of the card below set on the h3, and the link must not - // paint it the link blue over them or underline it. The colour + // paint it the link blue over them or underline it. The color // photograph and the blue name are the hover and the focus // signal, so the whole card reads as the target. .person_card_link { @@ -178,7 +185,7 @@ display: block; width: 100%; - // In colour, at rest, as the rows of /people/ and the + // In color, at rest, as the rows of /people/ and the // portrait of a person page are. The photographs used to be grey until // the pointer was on them, which a touch screen never // undid, and a grid of grey faces reads as an archive @@ -200,7 +207,7 @@ // The side padding keeps the text off the border now that // the card has none. padding: 5px 10px 0; - // Centred, like the icon row under it. The name and the role + // Centered, like the icon row under it. The name and the role // used to sit on the left edge while the icons sat in the // middle, so one card showed two alignments. text-align: center; @@ -210,7 +217,7 @@ // One size on every card. The size used to be a share of // the card so a long name could stay on one line, but // that made a long name visibly smaller than its - // neighbours and read as a different heading level + // neighbors and read as a different heading level // rather than as the same name in less room. font-size: 1.2em; // 3px here against 7px over the icons. What a reader @@ -240,7 +247,7 @@ p { margin-bottom: 0; // Italic sets the role apart from the name above it, - // which is the same colour and only a little larger. + // which is the same color and only a little larger. font-style: italic; // Smaller than the name, including a long name. At the // inherited 16px the role was larger than any name that @@ -326,13 +333,13 @@ } } - // With no border to colour, the hover and the focus are the - // photograph in colour and the name in blue, which the rules + // With no border to color, the hover and the focus are the + // photograph in color and the name in blue, which the rules // below and above set. The card has no outline of its own to // give. - // Keyboard focus shows the colour photo too, because the card holds + // Keyboard focus shows the color photo too, because the card holds // two focusable triggers. &:hover, &:focus-within { diff --git a/themes/pybcn_theme/assets/scss/people_index.scss b/themes/pybcn_theme/assets/scss/people_index.scss index 0dc8e970a..77f905b25 100644 --- a/themes/pybcn_theme/assets/scss/people_index.scss +++ b/themes/pybcn_theme/assets/scss/people_index.scss @@ -114,7 +114,7 @@ } // The placeholder of a person with no photo, at the size of the photo - // of a row. The colours and the letters are the shared rule at the end + // of a row. The colors and the letters are the shared rule at the end // of this file; the page of the person sets its own size in // people_page.scss. .person_initials { @@ -166,7 +166,7 @@ // The sentence of the second line, "Speaker at 3 events:", in the grey // and the size of the pages after it. The italic "at" and the bold // count are the markup of the row of the Events table of the person - // page, so the two read alike; the count is in the colour of the text, + // page, so the two read alike; the count is in the color of the text, // so the number stands out of the grey line. // The glyph of a role, in front of the word it marks. Same box as the // marker of a page below, so the two lines of a row hang alike. @@ -268,10 +268,10 @@ } } -// The placeholder of a person with no photo: the initials on a colour from +// The placeholder of a person with no photo: the initials on a color from // the name, drawn by partials/person_placeholder.html, which is the one // place to change it (its header says why). A round badge, white text, the -// ten colours below: every one of them is at 5:1 or more under white (WCAG +// ten colors below: every one of them is at 5:1 or more under white (WCAG // 1.4.3 asks 4.5:1), measured with the WCAG relative luminance formula when // they were chosen. Upright and at the normal weight of a heading, and // line-height 1 so the letters sit in the middle of the circle. The size is diff --git a/themes/pybcn_theme/assets/scss/people_page.scss b/themes/pybcn_theme/assets/scss/people_page.scss index 2632a4db2..80370d063 100644 --- a/themes/pybcn_theme/assets/scss/people_page.scss +++ b/themes/pybcn_theme/assets/scss/people_page.scss @@ -74,7 +74,7 @@ } // The placeholder of a person with no photo, at the size of the - // portrait: the initials on a colour, the shared rule of + // portrait: the initials on a color, the shared rule of // people_index.scss, five times the size of the row. .person_initials { flex: 0 0 auto; @@ -172,7 +172,7 @@ // give their lists a disc and a 1.25em indent on top of their own. // The day under a video is a grey line with a link in it, and a link - // inside a line of the same colour needs a second mark (WCAG 1.4.1), + // inside a line of the same color needs a second mark (WCAG 1.4.1), // the rule talks.scss applies to a caption and meetup.scss to the // source line. axe reported link-in-text-block on every talk row. .talk_meta a { @@ -213,7 +213,7 @@ // The last block, how the page is made and how to correct it: smaller // than the content it follows, and it reads as a note, as the source // line of a meetup page does. A link inside a sentence needs a second mark besides the - // colour (WCAG 1.4.1), the rule meetup.scss and talks.scss apply. + // color (WCAG 1.4.1), the rule meetup.scss and talks.scss apply. .person_correction p { color: $text-grey; font-size: 0.9rem; @@ -321,8 +321,8 @@ // three is after the same page. focus-within does // the same for the keyboard, where the link is what // takes focus. The glyph drops its grey and comes - // back in colour, which is the only place on the - // page a role shows its own colour. + // back in color, which is the only place on the + // page a role shows its own color. li:hover, li:focus-within { .role_emoji { @@ -372,7 +372,7 @@ } - // A colour change, not a move, so there is nothing + // A color change, not a move, so there is nothing // for prefers-reduced-motion to turn off. .role_emoji, strong { @@ -457,8 +457,8 @@ // // Desaturated, so the glyph sits with the black icons // of Social Links rather than being the one spot of - // colour in the lists. grayscale and nothing else: a - // colour emoji is a shaded picture, and in grey it is + // color in the lists. grayscale and nothing else: a + // color emoji is a shaded picture, and in grey it is // a light one, which is what this list wants. The // marker labels the row; the text beside it is what // the reader is here for, and a grey mark does not @@ -481,7 +481,7 @@ // some platforms and never a style. line-height: 1 // keeps the glyph from opening the line box of its // row further than its own height, and middle-aligned - // the text sits on the centre of the glyph instead of + // the text sits on the center of the glyph instead of // on its bottom edge. .role_emoji { display: inline-block; diff --git a/themes/pybcn_theme/assets/scss/photo_gallery.scss b/themes/pybcn_theme/assets/scss/photo_gallery.scss index 4a73a550f..64d66a682 100644 --- a/themes/pybcn_theme/assets/scss/photo_gallery.scss +++ b/themes/pybcn_theme/assets/scss/photo_gallery.scss @@ -29,7 +29,7 @@ $quote-rule: #ced4da; // 900x506 and 379x675 at 1280px, 358x201 and 358x636 at 390px. $photo-max-height: 675px; -// There is no band of colour behind the section, and no rule above it any +// There is no band of color behind the section, and no rule above it any // more. The gallery sat on a light grey band, with every card on it, until // 2026-10-14. Each figure is its own card, on the white of the page, // and the air between the cards is what separates them. The hr above the @@ -40,7 +40,7 @@ $photo-max-height: 675px; .photo_gallery { // The gallery is the last section and it is set apart from the - // programme, so it does not have to sit inside the reading column the + // program, so it does not have to sit inside the reading column the // text uses. Breaking out of it gives a photograph 900px instead of // 775px, measured at the 1140px container of this theme: the section is // 902px, and the 1px border of the card on each side leaves 900 for the @@ -54,10 +54,10 @@ $photo-max-height: 675px; // worse than any saving is worth. // 1200px is the xl breakpoint of Bootstrap 4, written out because this // file is compiled without the Bootstrap mixins in scope. It was 992, - // the lg one, and that was too early: margin-left 50% centres the + // the lg one, and that was too early: margin-left 50% centers the // section on its containing block, which is the col-md-9 of the page // and not the window, so between 992px and 1200px the 902px section - // landed off centre and ran past the right edge of the screen. Measured + // landed off center and ran past the right edge of the screen. Measured // on the live site, the event page was 1067px wide on a 992px screen // and 1083px on a 1024px one, which is the same sideways drag issue // #212 reports for the schedule, on a different element and at a @@ -104,7 +104,7 @@ $photo-max-height: 675px; // The cap on the height: $photo-max-height, with the reason // beside it. The box of the image keeps the width of the card // (card-img-top sets width 100%), and the photograph is - // painted inside it at its own ratio, centred, so a portrait + // painted inside it at its own ratio, centered, so a portrait // shows at 380x675 on a white card instead of 900x1600 and a // landscape up to 4:3 is not touched. object-fit and not // width auto: with width auto a landscape whose source is @@ -156,8 +156,8 @@ $photo-max-height: 675px; // The links of the post: a mention, a hashtag, or a URL the post // wrote. Underlined, because they sit inside a run of text where a - // colour alone is the only thing that would mark them, and WCAG - // 1.4.1 asks for more than colour. A mention and a hashtag carry + // color alone is the only thing that would mark them, and WCAG + // 1.4.1 asks for more than color. A mention and a hashtag carry // the X mark in front (partials/caption_links.html), smaller than // the mark of a credit line because it sits inside a sentence, and // the underline stops at it: .icon_x is an inline-block. @@ -179,7 +179,7 @@ $photo-max-height: 675px; color: $dark-grey; // The line goes to the page of the talk. Same treatment as the - // credit below it: the colour of the line at rest with an + // credit below it: the color of the line at rest with an // underline, and the PyBCN blue under the pointer. The underline // is the second mark WCAG 1.4.1 asks for, and keeping the grey // stops two links in one figcaption from shouting at each other. @@ -212,7 +212,7 @@ $photo-max-height: 675px; align-items: baseline; // The link to this figure: #3 for the third photo of the day. It - // takes the same colour and underline as the credit, and the + // takes the same color and underline as the credit, and the // margin pushes it to the right edge when there is no credit to // sit at the left. .photo_number { @@ -223,7 +223,7 @@ $photo-max-height: 675px; color: $icon-grey; transition: color 0.15s linear; // Underlined, so the credit reads as a link before the pointer - // reaches it. Grey text in a grey line said nothing, and colour + // reaches it. Grey text in a grey line said nothing, and color // alone would not say it either: WCAG 1.4.1 asks for a second // mark, and this is the mark a link takes everywhere else. text-decoration: underline; diff --git a/themes/pybcn_theme/assets/scss/sponsors.scss b/themes/pybcn_theme/assets/scss/sponsors.scss index e083eaab5..d5308c245 100644 --- a/themes/pybcn_theme/assets/scss/sponsors.scss +++ b/themes/pybcn_theme/assets/scss/sponsors.scss @@ -124,7 +124,7 @@ $sponsor-gap: 1rem; // whole card scales and not the logo inside it, because a // logo that grows alone spills over the padding and crosses // the white edge onto the band. 7px of growth against a gap - // of 12px, so it never touches its neighbour. + // of 12px, so it never touches its neighbor. transform: scale(1.04); z-index: 1; } diff --git a/themes/pybcn_theme/assets/scss/talks.scss b/themes/pybcn_theme/assets/scss/talks.scss index 480dccaaf..c4082dfe1 100644 --- a/themes/pybcn_theme/assets/scss/talks.scss +++ b/themes/pybcn_theme/assets/scss/talks.scss @@ -22,7 +22,7 @@ // announcement, with the rule down the left side that the caption of a // gallery photo takes (.photo_caption in photo_gallery.scss, which has // the reason for not using Bootstrap's .blockquote: it sets 1.25rem and - // would print the abstract larger than the page). The colour of the + // would print the abstract larger than the page). The color of the // body text stays, because the abstract is the body of this page. // Italic, as the caption is and as a quotation is set in print, so // the two blockquotes of the site read alike; it was upright and did @@ -139,7 +139,7 @@ // The video of the talk, under the names: the link // partials/video_link.html prints, with the YouTube mark in front. - // Underlined, because colour alone cannot mark a link in a run of + // Underlined, because color alone cannot mark a link in a run of // text (WCAG 1.4.1, the rule .photo_source already follows). The mark // is an inline-block, so the underline is not drawn through it. .talk_video { @@ -201,7 +201,7 @@ } } -// A link inside a sentence needs a second mark besides the colour, which is +// A link inside a sentence needs a second mark besides the color, which is // WCAG 1.4.1 and the rule this repository already applies to .photo_source. // axe reported this one as link-in-text-block. .talk_photo figcaption a, diff --git a/themes/pybcn_theme/layouts/_default/contact.html b/themes/pybcn_theme/layouts/_default/contact.html index b15a957f5..8cdb4a177 100644 --- a/themes/pybcn_theme/layouts/_default/contact.html +++ b/themes/pybcn_theme/layouts/_default/contact.html @@ -10,7 +10,7 @@

    PyBCN

    {{ range sort $.Site.Params.social_items "weight" }} - + {{ end }}


    {{ end }} @@ -19,7 +19,7 @@

    PyLadiesB

    {{ range sort $.Site.Params.social_items_pyladies "weight" }} - + {{ end }}

    diff --git a/themes/pybcn_theme/layouts/_default/event.html b/themes/pybcn_theme/layouts/_default/event.html index e65e1d675..8e2933ece 100644 --- a/themes/pybcn_theme/layouts/_default/event.html +++ b/themes/pybcn_theme/layouts/_default/event.html @@ -19,7 +19,7 @@ YouTube with 20 videos and no photograph, so its gallery is the Talks & Videos subsection alone (the header of partials/gallery_content.html says why the videos are there and - not under the programme, and why a page with a Talks block prints + not under the program, and why a page with a Talks block prints them there instead). */ -}} {{ $gallery := partialCached "gallery_content.html" . .RelPermalink }} @@ -74,7 +74,7 @@ (partials/hero_header.html, which also writes the kind), plus the captions of the gallery, each at its figure (partials/photo_gallery.html). The sections of - the page, the programme grid, the sponsors, and the + the page, the program grid, the sponsors, and the people grids are out: a talk and a person have pages of their own, and a name indexed here as well would match twice. The venue is not printed on this page (the row of @@ -99,7 +99,7 @@ {{- end }} {{- /* How many people came, which is a count and not a registration: AGENTS.md keeps the two words apart, and - the meetup pages say "Registrations" because an RSVP of + the meetup pages say "RSVPs" because an RSVP of Meetup is an intention. An edition sold its tickets elsewhere, so the only number it has is the one the association counted and published on the day. The front @@ -144,10 +144,10 @@

    {{ $section.title }}

    the CSS grid, so a page with an agenda and no eventTimes has no grid to draw: it would emit grid-template-rows: repeat(0) and stack every block of the day on one line. The two pre-Hugo - programmes, PyDay BCN 2018 and 2019, are in that state on + programs, PyDay BCN 2018 and 2019, are in that state on purpose. They carry agenda, talks and rooms because a photo of the gallery joins to a talk by id, and they publish the - programme the association froze in their own body: the pasted + program the association froze in their own body: the pasted agenda table of 2018 and the calendar embed of 2019. Give either one eventTimes and numTracks and its grid appears. */ -}} {{ if and .Params.agenda .Params.eventTimes }} @@ -162,7 +162,7 @@

    Schedule

    {{ end }} - {{/* The talks of an edition that has them and has no programme + {{/* The talks of an edition that has them and has no program grid, as rows, where the grid would be: the rows of partials/talk_rows.html, the ones a meetup page draws, so the two read alike. Each row links to the page of its talk, @@ -172,9 +172,9 @@

    Schedule

    no record of the room or the hour of any of them, so no grid to draw. The gate is the absence of agenda and not of eventTimes: PyDay BCN 2018 and 2019 carry an agenda with no - eventTimes on purpose (see above) and publish the programme + eventTimes on purpose (see above) and publish the program in their body, and a list of rows under it would print the - programme twice. + program twice. The heading carries both counts, "Talks (32) & Videos (29)": each row prints the video of its talk, so this block @@ -192,7 +192,7 @@

    Talks ({{ len .Params.talks }}){{ with $nvideos }} &am {{ end }} - {{/* The videos of a day with a programme grid are not here: + {{/* The videos of a day with a program grid are not here: they are the Talks & Videos subsection of the gallery at the end of the page, with the photographs (partials/photo_gallery.html). A Videos block sat here, @@ -202,7 +202,7 @@

    Talks ({{ len .Params.talks }}){{ with $nvideos }} &am the gallery of a page with the Talks block above. */}} {{/* The recordings of a whole session, which belong to the day and - to no talk, right after the programme: see + to no talk, right after the program: see partials/session_videos.html. No edition carries the block today (the three that do are meetups, on layouts/_default/meetup.html); bin/import-videos may write @@ -238,9 +238,9 @@

    {{ $section.title }}

    {{/* The gallery is last, after the sponsors and the people of the day. It is what the day left behind, the photographs the association published and the recordings, and the rest of - the page is the day itself: the programme, who paid for it, + the page is the day itself: the program, who paid for it, and who ran it. It used to sit between the schedule and the - sponsors, which read as part of the programme. */}} + sponsors, which read as part of the program. */}} {{ partial "photo_gallery.html" . }} diff --git a/themes/pybcn_theme/layouts/_default/events_index.html b/themes/pybcn_theme/layouts/_default/events_index.html index 0ac76a072..b9b347c17 100644 --- a/themes/pybcn_theme/layouts/_default/events_index.html +++ b/themes/pybcn_theme/layouts/_default/events_index.html @@ -95,7 +95,7 @@ bin/check-content reports it. The italics are a style and not an em element: the venue is not stressed, it is set apart. - The gallery is partials/count_card.html: the talks of the programme of + The gallery is partials/count_card.html: the talks of the program of the day, the photos its gallery renders, and the videos its page prints, an icon and a number each. The counts come from partials/listing_counts.html, the one walk of the site that also feeds @@ -104,11 +104,13 @@ include the recording of a whole session, which belongs to no talk) is written there once for the three listings. - Reached through layout: events_index in content/events/_index.md, and not - through a layouts/events/list.html, because Page.Section of a nested - section is its top level: an events/list.html would also draw - /events/pyday_bcn/, /events/pydatabcn/ and /events/other_events/, which - are index pages of a series and want the fallback list they have. + Reached through layout: events_index in content/events/_index.md, + which Hugo looks up before layouts/events/list.html. That file draws + the index pages of the four series, /events/meetups/, + /events/pyday_bcn/, /events/pydatabcn/, and /events/other_events/, + with the same body as this one, cut to the events of the series (they + took the fallback list of titles until 2026-10-25). The two layouts + differ only in what partials/listing_total.html counts for their h1. monthly_events.md selects its own layout the same way. What is a row. A page under content/events/ that carries a year in its @@ -154,55 +156,17 @@ year and by month and prints it. Both moved out of this layout on 2026-10-16, when the home page started printing the ten newest rows (layouts/_default/home.html): one row and one table for the two pages, - so the home page cannot print an event differently from this one. This - layout keeps what is its own: the intro, the jump bar, and the legend. + so the home page cannot print an event differently from this one. The + rest, the intro, the tabs of the series (partials/events_tabs.html, + All and the four series with their counts, as /talks/ and /people/ + have), the jump bar, the legend, and the call to the table, is + partials/event_listing.html since 2026-10-25, shared with + layouts/events/list.html, so a series page cannot list its events + differently from this one either. This layout is the header above and + one call. */ -}} {{ define "main" }}
    - - {{ with .Content }}
    {{ . }}
    {{ end }} - - {{- /* The counts of the legend, from one cached walk of the site: see - partials/listing_counts.html. The card of every row reads the - same walk, inside partials/event_row.html. */ -}} - {{- $counts := partialCached "listing_counts.html" site "listing-counts" -}} - - {{- /* One row per event, through partials/event_row.html, then sorted - by the key of the row, which reads newest first: the year, the - date, and then the title and the URL as the tiebreak. The same - rows, sorted the same way, are what the home page keeps the - first ten of. */ -}} - {{- $rows := slice -}} - {{- range .RegularPagesRecursive -}} - {{- if not .Params.year }}{{ continue }}{{ end -}} - {{- $rows = $rows | append (partial "event_row.html" .) -}} - {{- end -}} - {{- $rows = sort $rows "key" -}} - - {{- /* The years, as links to the groups below, through the bar - partials/jump_bar.html draws for this page and for /people/. The - far end of 281 rows under 20 years is many screens of scrolling - away. Only the years that have a row are here, in the order the - table draws them, so the bar reads newest first the way the page - does: a row whose year differs from the row before it opens a - year, which is the cut partials/event_table.html makes. */}} - {{- $jump := slice -}} - {{- $open := "" -}} - {{- range $rows }}{{ if ne .year $open }}{{ $jump = $jump | append (dict "anchor" .year "text" .year) }}{{ $open = .year }}{{ end }}{{ end }} - {{ partial "jump_bar.html" (dict "label" "Jump to a year" "items" $jump) }} - - {{- /* The legend: each marker the table draws, with how many rows carry - it, through partials/marker_legend.html. The counts come from - the type of every row through the same partial the rows do, so - the legend and the rows cannot disagree. It sits between the bar - and the table, right above the rows it explains. */ -}} - {{- $legend := slice -}} - {{- range $token, $entry := site.Data.event_emoji -}} - {{- $legend = $legend | append (dict "emoji" $entry.emoji "one" $entry.one "many" $entry.many "count" (int (default 0 (index $counts.events $token)))) -}} - {{- end }} - {{ partial "marker_legend.html" (dict "label" "Event types" "items" $legend) }} - - {{ partial "event_table.html" (dict "rows" $rows) }} - + {{ partial "event_listing.html" . }}
    {{ end }} diff --git a/themes/pybcn_theme/layouts/_default/home.html b/themes/pybcn_theme/layouts/_default/home.html index 4ccba36c2..b94ab07ef 100644 --- a/themes/pybcn_theme/layouts/_default/home.html +++ b/themes/pybcn_theme/layouts/_default/home.html @@ -2,7 +2,7 @@ The home page. The blocks, in order: the hero - with the four counts of the Archive, About Python Barcelona with the + with the six counts of the Archive, About Python Barcelona with the video, the two Meetup groups, the recent events, the photographs, About us with the faces of the board and the committee, Take part, and Our friends. @@ -23,6 +23,43 @@ {{- $counts := partialCached "listing_counts.html" site "listing-counts" -}} {{- $sponsors_total := len (partial "sponsor_ids.html" site) -}} {{- $glyphs := site.Data.role_emoji -}} +{{- /* The rule of the tiles: the number of a tile is the number of the + page it leads to, counted by the partial that page counts with, + so a reader who follows a tile finds the figure again in the + heading or the text of the page. Events, Talks, and People are the + totals of the h1 of the three listings (partials/listing_total.html + reads the same map), Sponsors is the h1 of /sponsors/, the RSVPs + are the sum the Attendees page prints (partials/meetup_rsvps.html), + and the board and the committee are the people the Who we are page + lists under its two home_faces levels, which the faces of About us + below draw from the same front matter. */ -}} +{{- /* The board and the committee: the ids under the levels of + content/pybcn_association/organizers.md that carry home_faces, the + two bodies that run the association today (the former board and + the collaborators are not in the count), each person once, so a + person on both bodies is one. The link lands on the heading of the + first of those levels, which partials/people-grid.html gives an id + from its name. */ -}} +{{- $who := site.GetPage "/pybcn_association/organizers" -}} +{{- $board_ids := dict -}} +{{- $board_anchor := "" -}} +{{- range $who.Params.people_levels -}} + {{- if not .home_faces }}{{ continue }}{{ end -}} + {{- if not $board_anchor }}{{ $board_anchor = printf "#%s" (anchorize .name) }}{{ end -}} + {{- range .people -}} + {{- $id := . -}} + {{- if reflect.IsMap . }}{{ $id = .id }}{{ end -}} + {{- $board_ids = merge $board_ids (dict $id true) -}} + {{- end -}} +{{- end -}} +{{- $board_total := len $board_ids -}} +{{- /* The RSVPs: the sum of the attendance field over the pages of + content/events/meetups/, which is the yes count of Meetup and not + who came (AGENTS.md: RSVPs are not attendance). The label says + Meetup, because the figure is Meetup's and covers no PyDay. The + tile leads to the Attendees page, which prints the same sum and + says what it is. */ -}} +{{- $rsvps_total := (partialCached "meetup_rsvps.html" site "meetup-rsvps").total -}} {{- $events := site.GetPage "/events" -}} {{- $rows := slice -}} {{- range $events.RegularPagesRecursive -}} @@ -35,11 +72,27 @@ + {{- /* Six tiles. The label is the title of the page the tile + leads to, except where that title would say something + else: the board and the committee are two levels of the + Who we are page, so the tile names them and lands on + their heading, and the RSVPs are a sum the Attendees + page prints, so the tile names the sum. The People + tile carries a caption, so the number under the word + is not read as the people who run the association, + which is the tile beside it. A number is printed with + a thousands separator, so 8917 reads as 8,917 next to + 607. The glyphs are the ones of data/role_emoji.yaml, + as on /people/, except the speech balloon of the + talks: a talk type has a Font Awesome icon and no emoji + (partials/event_types.html). */ -}} {{- $tiles := slice - (dict "path" "/events" "total" $counts.events_total "glyph" (index $glyphs "Events")) - (dict "path" "/talks" "total" $counts.talks_total "glyph" (index $glyphs "Speaker")) - (dict "path" "/people" "total" $counts.people_total "glyph" (index $glyphs "*")) - (dict "path" "/sponsors" "total" $sponsors_total "glyph" (index $glyphs "Collaborator")) -}} + (dict "path" "/events" "total" $counts.events_total "glyph" (index $glyphs "Events")) + (dict "path" "/talks" "total" $counts.talks_total "glyph" "💬") + (dict "path" "/people" "total" $counts.people_total "glyph" (index $glyphs "*") "caption" "Speakers, organizers, and others") + (dict "path" "/pybcn_association/organizers" "total" $board_total "glyph" (index $glyphs "Board (2026)") "label" "Board and Committee" "anchor" $board_anchor) + (dict "path" "/people/role/attendees" "total" $rsvps_total "glyph" (index $glyphs "Attendees") "label" "Meetup RSVPs") + (dict "path" "/sponsors" "total" $sponsors_total "glyph" (index $glyphs "Collaborator")) -}}

    Python Barcelona, since {{ $first_year }}

    @@ -49,10 +102,10 @@

    Python Barcelona, since {{ $first_year }}

    {{- $tile := . }} {{- with site.GetPage .path }}
  3. - + - {{ $tile.total }} - {{ .Title }} + {{ lang.FormatNumberCustom 0 $tile.total }} + {{ default .Title $tile.label }}{{ with $tile.caption }}{{ . }}{{ end }}
  4. {{- else }}{{ errorf "home: the page %q is missing" $tile.path }}{{ end }} @@ -132,7 +185,7 @@

    Recent events

    -

    Our favourite pictures from our favourite events

    +

    Our favorite pictures from our favorite events