From 130b710fadbac07502d04090b129dbbc5ac0f118 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 13:25:13 +0100 Subject: [PATCH 01/18] Add schema.org semantic data to events page This change adds structured semantic data (JSON-LD) to the events page, making event information machine-readable for search engines and other tools. Changes: - Add city, country, state, and venue fields to Event dataclass - Generate schema.org Event markup with PostalAddress for physical events - Use VirtualLocation for virtual events - Compute location display strings from structured fields - Add structured data to sample events in events.yaml - Integrate validation in GitHub Actions using structured-data-testing-tool - Stub project downloads when NODOWNLOAD=1 to avoid rate limits The semantic data includes proper geographic information using PostalAddress with addressLocality (city), addressCountry (country), and addressRegion (state) fields, making events more discoverable and accessible. --- .github/workflows/build.yml | 17 + .github/workflows/build_pr.yml | 17 + data/events.yaml | 27 +- make_site.py | 108 +++- package-lock.json | 953 +++++++++++++++++++++++++++++++++ package.json | 25 + templates/events.html | 16 +- 7 files changed, 1149 insertions(+), 14 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 256ffbee0a..ede6ea097c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,6 +52,23 @@ jobs: github_ref: ${{ github.ref }} ZULIP_KEY: ${{ secrets.ZULIP_KEY }} + - name: setup Node.js + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version: '24' + + - name: install Node.js dependencies + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + run: npm ci + + - name: validate semantic data in events.html + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + run: | + echo "Validating schema.org Event markup in events.html..." + npm run validate:events + echo "✓ Semantic data validation passed!" + - name: Upload artifact id: upload-artifact if: ${{ !cancelled() && (steps.build.outcome == 'success') }} diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 9332c22190..9a393efb12 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -39,6 +39,23 @@ jobs: run: | ./make_site.py + - name: setup Node.js + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version: '24' + + - name: install Node.js dependencies + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + run: npm ci + + - name: validate semantic data in events.html + if: ${{ !cancelled() && (steps.build.outcome == 'success') }} + run: | + echo "Validating schema.org Event markup in events.html..." + npm run validate:events + echo "✓ Semantic data validation passed!" + - name: Upload artifact id: upload-artifact if: ${{ !cancelled() && (steps.build.outcome == 'success') }} diff --git a/data/events.yaml b/data/events.yaml index b5c75c4be5..0021e646ec 100644 --- a/data/events.yaml +++ b/data/events.yaml @@ -2,7 +2,8 @@ url: https://pitmonticone.github.io/ItaLean2025/ start_date: December 9 2025 end_date: December 12 2025 - location: Bologna, Italy + city: Bologna + country: Italy type: conference - title: "Lean Together 2026" @@ -16,21 +17,27 @@ url: https://leaning.in/2026/ start_date: March 12 2026 end_date: March 12 2026 - location: Spielfeld, Berlin, Germany + venue: Spielfeld + city: Berlin + country: Germany type: conference - title: Techniques and Tools for the Formalization of Analysis url: https://icerm.brown.edu/program/topical_workshop/tw-26-ttfa start_date: May 11 2026 end_date: May 15 2026 - location: ICERM, Providence, RI, USA + venue: ICERM + city: Providence + state: RI + country: USA type: workshop - title: Proof assistant users meetup in Ghent url: https://www.meetup.com/nl-NL/sysghent/events/311198787 start_date: October 27 2025 end_date: October 27 2025 - location: Ghent, Belgium + city: Ghent + country: Belgium type: workshop - title: Lean for the Curious Mathematician 2026 (Italy) @@ -38,6 +45,9 @@ start_date: September 7 2026 end_date: September 11 2026 location: SNS, Cortona, Italy + venue: SNS + city: Cortona + country: Italy type: workshop - title: Formalising Algebraic Geometry in Lean @@ -45,6 +55,8 @@ start_date: November 19 2025 end_date: November 21 2025 location: Heidelberg, Germany + city: Heidelberg + country: Germany type: workshop - title: Lean for PDEs @@ -52,6 +64,9 @@ start_date: October 6 2025 end_date: October 9 2025 location: Berkeley, CA, USA + city: Berkeley + state: CA + country: USA type: workshop - title: "VSTTE 2025: Conference on Verified Software: Theories, Tools, and Experiments" @@ -482,7 +497,9 @@ end_date: January 17 2025 - title: "Leaning In! 2025" - location: Berlin, DE + location: Berlin, Germany + city: Berlin + country: Germany type: workshop url: https://leaning.in start_date: March 13 2025 diff --git a/make_site.py b/make_site.py index b33c5d0e31..8ceed2afec 100755 --- a/make_site.py +++ b/make_site.py @@ -290,12 +290,104 @@ class TheoremForWebpage: @dataclass class Event: title: str - location: str type: str url: str = 'TBA' start_date: str = '' end_date: str = '' date_range: str = 'TBA' + schema_org_json: str = '' + location: str = '' # Computed from structured fields or explicitly provided + city: Optional[str] = None + country: Optional[str] = None + state: Optional[str] = None + venue: Optional[str] = None + + def compute_location(self) -> str: + """Compute location string from structured fields.""" + # For virtual events + if self.location.lower() in ['virtual', 'online']: + return self.location + + # Build location from structured fields + parts = [] + if self.venue: + parts.append(self.venue) + if self.city: + parts.append(self.city) + if self.state: + parts.append(self.state) + if self.country: + parts.append(self.country) + + if parts: + return ', '.join(parts) + elif self.location: + # Fall back to explicit location if provided + return self.location + else: + return 'TBA' + +def generate_schema_org_json(event: Event) -> str: + """Generate schema.org JSON-LD for an event.""" + try: + # Parse dates to ISO 8601 format + start_date_obj = datetime.strptime(event.start_date, '%B %d %Y') + start_date_iso = start_date_obj.strftime('%Y-%m-%d') + end_date_obj = datetime.strptime(event.end_date, '%B %d %Y') + end_date_iso = end_date_obj.strftime('%Y-%m-%d') + except (ValueError, TypeError, AttributeError): + # If we can't parse the dates, don't generate schema.org data + return '' + + # Build the schema.org structure + schema_data = { + "@context": "https://schema.org", + "@type": "Event", + "name": event.title, + "description": event.title, + "url": event.url, + "startDate": start_date_iso, + "endDate": end_date_iso, + } + + # Add location - determine if virtual or physical + if event.location.lower() in ['virtual', 'online']: + schema_data["eventAttendanceMode"] = "https://schema.org/OnlineEventAttendanceMode" + schema_data["location"] = { + "@type": "VirtualLocation", + "url": event.url + } + else: + schema_data["eventAttendanceMode"] = "https://schema.org/OfflineEventAttendanceMode" + + # Use structured address data if available, otherwise fall back to location string + if event.city and event.country: + address = { + "@type": "PostalAddress", + "addressLocality": event.city, + "addressCountry": event.country + } + # Add state/region for US addresses if available + if event.state: + address["addressRegion"] = event.state + + schema_data["location"] = { + "@type": "Place", + "name": event.location, + "address": address + } + else: + # Fall back to simple Place with just name + schema_data["location"] = { + "@type": "Place", + "name": event.location + } + + # Add event status - assume scheduled for future events + schema_data["eventStatus"] = "https://schema.org/EventScheduled" + + # Convert to pretty-printed JSON + return json.dumps(schema_data, indent=2) @dataclass class Course: @@ -553,7 +645,11 @@ def format_date_range(event): new_events = sorted((e for e in events if (not e.end_date) or datetime.strptime(e.end_date, '%B %d %Y').date() >= present), key=lambda e: datetime.strptime(e.end_date, '%B %d %Y').date()) for e in old_events + new_events: + # Compute location from structured fields if not explicitly provided + if not e.location or e.location == '': + e.location = e.compute_location() e.date_range = format_date_range(e) + e.schema_org_json = generate_schema_org_json(e) @dataclass @@ -573,7 +669,7 @@ class Project: oprojects_3 = yaml.safe_load(h_file) pkl_dump('oprojects_3', oprojects_3) else: - oprojects_3 = pkl_load('oprojects_3', []) + oprojects_3 = {} # Use empty dict when not downloading projects_3 = [] @@ -586,8 +682,7 @@ class Project: projects_3.append(Project(name, project['organization'], descr, project['maintainers'], stars, github_repo.html_url)) projects_3.sort(key = lambda p: p.stars, reverse=True) pkl_dump('projects_3', projects_3) -else: - projects_3 = pkl_load('projects_3', []) +# else: projects_3 stays as empty list [] if DOWNLOAD: download( @@ -597,7 +692,7 @@ class Project: oprojects_4 = yaml.safe_load(h_file) pkl_dump('oprojects_4', oprojects_4) else: - oprojects_4 = pkl_load('oprojects_4', []) + oprojects_4 = [] # Use empty list when not downloading projects_4 = [] @@ -611,8 +706,7 @@ class Project: projects_4.append(Project(name, github_repo.owner.login, descr, None, stars, github_repo.html_url)) projects_4.sort(key = lambda p: p.stars, reverse=True) pkl_dump('projects_4', projects_4) -else: - projects_4 = pkl_load('projects_4', []) +# else: projects_4 stays as empty list [] if DOWNLOAD: # We used to use this count but it didn't include mathlib3 contributors diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..6c4b94752c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,953 @@ +{ + "name": "leanprover-community.github.io", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "leanprover-community.github.io", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "structured-data-testing-tool": "^4.5.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/columnify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==", + "dev": true, + "license": "BSD-like", + "dependencies": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "node_modules/css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/structured-data-testing-tool": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/structured-data-testing-tool/-/structured-data-testing-tool-4.5.0.tgz", + "integrity": "sha512-EjNG7L4PllMkTPlfxpyrKT5X0ub3C3PZIqAsjSDVUlnhRE/A5zoNTEukIxYjYlv8LgH+aqxfS0XwczZosbJVew==", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^2.4.2", + "columnify": "^1.5.4", + "get-stream": "^5.1.0", + "is-stream": "^2.0.0", + "jmespath": "^0.15.0", + "node-fetch": "^2.6.0", + "validator": "^11.0.0", + "web-auto-extractor": "^1.0.17", + "yargs": "^13.2.4" + }, + "bin": { + "sdtt": "bin/cli.js" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validator": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", + "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-auto-extractor": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/web-auto-extractor/-/web-auto-extractor-1.0.17.tgz", + "integrity": "sha512-V+ekXwPSD8c2FqZWpdxJ7P2fvlDbNiEgSdrp+pP5RTsUHOb4gzvfbdmG5ymd1b/6gtQ6seNPesqjZQ1DCMxIww==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-polyfill": "^6.8.0", + "cheerio": "^0.22.0", + "htmlparser2": "^3.9.1" + }, + "engines": { + "node": ">=4.4" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..b3bbdd0391 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "leanprover-community.github.io", + "version": "1.0.0", + "description": "The deployed website lives on the `master` branch of this repository. To make changes to the website, please fork the repository and make a PR against the [`lean4`](https://github.com/leanprover-community/leanprover-community.github.io/tree/lean4) branch. Once your PR is merged, CI will automatically deploy the changes to the `master` branch.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "validate:events": "sdtt --file build/events.html --schemas Event" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jessealama/leanprover-community.github.io.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "commonjs", + "bugs": { + "url": "https://github.com/jessealama/leanprover-community.github.io/issues" + }, + "homepage": "https://github.com/jessealama/leanprover-community.github.io#readme", + "devDependencies": { + "structured-data-testing-tool": "4.5.0" + } +} diff --git a/templates/events.html b/templates/events.html index a8bfee4432..e94c20c989 100644 --- a/templates/events.html +++ b/templates/events.html @@ -25,7 +25,13 @@

Upcoming events

  • {{ e.title }} ({{ e.location }}. {{ e.date_range }}) {{ e.type }} -
  • + + {% if e.schema_org_json %} + + {% endif %} + {% endfor %} @@ -35,7 +41,13 @@

    Past events

  • {{ e.title }} ({{ e.location }}. {{ e.date_range }}) {{ e.type }} -
  • + + {% if e.schema_org_json %} + + {% endif %} + {% endfor %} {% endblock %} From 93791820168c6742d412b17cf1847b02f6b4ac86 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 13:32:37 +0100 Subject: [PATCH 02/18] Use venue name (not full location) for Place name in schema.org When a venue is specified, the Place name should be just the venue (e.g., 'Spielfeld') rather than the full computed location string (e.g., 'Spielfeld, Berlin, Germany'). The full address details are already captured in the PostalAddress structure. For events without a venue, the city name is used as the Place name. --- make_site.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make_site.py b/make_site.py index 8ceed2afec..e1d27974bd 100755 --- a/make_site.py +++ b/make_site.py @@ -371,9 +371,12 @@ def generate_schema_org_json(event: Event) -> str: if event.state: address["addressRegion"] = event.state + # Use venue as Place name if available, otherwise use city + place_name = event.venue if event.venue else event.city + schema_data["location"] = { "@type": "Place", - "name": event.location, + "name": place_name, "address": address } else: From 395357338a40c89f68f8a2ea82e25ec449653ca9 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 13:48:51 +0100 Subject: [PATCH 03/18] Use structured location data for all events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert all events from unstructured 'location' strings to structured fields (city, country, state, venue). This enables proper schema.org PostalAddress markup with addressLocality, addressCountry, and addressRegion. Changes: - 54 events updated with structured location data - State abbreviations expanded (RI, CA, MA, CO, PA, etc.) - Country names standardized (NL → Netherlands, UK → United Kingdom) - Venue abbreviations preserved (ICERM, ICTS, MSRI, etc.) - Virtual events unchanged (location: virtual) - Fixed typo: Tblisi → Tbilisi The Place name in schema.org now uses venue (if available) or city (as fallback), rather than the full location string. PostalAddress provides structured address details. All 70 events pass validation (100%). --- data/events.yaml | 179 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 123 insertions(+), 56 deletions(-) diff --git a/data/events.yaml b/data/events.yaml index 0021e646ec..e5a41f363b 100644 --- a/data/events.yaml +++ b/data/events.yaml @@ -28,7 +28,7 @@ end_date: May 15 2026 venue: ICERM city: Providence - state: RI + state: Rhode Island country: USA type: workshop @@ -44,7 +44,6 @@ url: https://leanprover.zulipchat.com/#narrow/channel/113486-announce/topic/Lean.20for.20the.20Curious.20Mathematician.202026/with/523718160 start_date: September 7 2026 end_date: September 11 2026 - location: SNS, Cortona, Italy venue: SNS city: Cortona country: Italy @@ -54,7 +53,6 @@ url: https://judithludwig.github.io/LeanWorkshop2025 start_date: November 19 2025 end_date: November 21 2025 - location: Heidelberg, Germany city: Heidelberg country: Germany type: workshop @@ -63,9 +61,8 @@ url: https://www.slmath.org/workshops/1180 start_date: October 6 2025 end_date: October 9 2025 - location: Berkeley, CA, USA city: Berkeley - state: CA + state: California country: USA type: workshop @@ -73,102 +70,121 @@ url: https://systemf.epfl.ch/etc/vstte2025/ start_date: October 6 2025 end_date: October 7 2025 - location: Menlo Park, USA + city: Menlo Park + country: USA type: conference - title: EuroProofNet final symposium url: https://europroofnet.github.io/Symposium/ start_date: September 8 2025 end_date: September 19 2025 - location: Orsay, France + city: Orsay + country: France type: conference - title: Mechanization and Mathematical Research url: https://www.lorentzcenter.nl/mechanization-and-mathematical-research.html start_date: September 15 2025 end_date: September 19 2025 - location: Leiden, the Netherlands + city: Leiden + country: Netherlands type: workshop - title: Summer School on Formalizing Mathematics in Lean url: https://utrechtsummerschool.nl/courses/science/formalizing-mathematics-in-lean start_date: July 21 2025 end_date: July 25 2025 - location: Utrecht, the Netherlands + city: Utrecht + country: Netherlands type: tutorial - title: Lean for Mathematicians url: https://sites.google.com/view/simonsleanworkshop2025 start_date: June 16 2025 end_date: June 27 2025 - location: New York, NY, USA + city: New York + state: New York + country: USA type: tutorial - title: Formalizing Class Field Theory url: https://www.claymath.org/events/formalizing-class-field-theory/ start_date: July 21 2025 end_date: July 25 2025 - location: Oxford, England + city: Oxford + country: United Kingdom type: workshop - title: Solving riddles with Lean url: https://sysghent.be/events/lean start_date: July 17 2025 end_date: July 17 2025 - location: Ghent, Belgium + city: Ghent + country: Belgium type: workshop - title: Lean for the Curious Mathematician (India) url: https://www.icts.res.in/discussion-meeting/LCMaths start_date: April 24 2025 end_date: April 27 2025 - location: ICTS, Bengaluru, India + venue: ICTS + city: Bengaluru + country: India type: workshop - title: Autoformalization for the Working Mathematician url: https://icerm.brown.edu/program/hot_topics_workshop/htw-25-aftwm start_date: April 24 2025 end_date: April 27 2025 - location: Providence, RI, USA + city: Providence + state: Rhode Island + country: USA type: workshop - title: Interactive Theorem Proving 2025 url: https://icetcs.github.io/frocos-itp-tableaux25/itp/ start_date: September 27 2025 end_date: October 3 2025 - location: Reykjavik, Iceland + city: Reykjavik + country: Iceland type: conference - title: AI for Mathematics and Theoretical Computer Science url: https://simons.berkeley.edu/workshops/simons-institute-theory-computing-slmath-joint-workshop-ai-mathematics-theoretical start_date: April 7 2025 end_date: April 11 2025 - location: Berkeley, CA, USA + city: Berkeley + state: California + country: USA type: workshop - title: Computational Algebraic Geometry Workshop url: https://sites.google.com/view/durhamcompalggeom/home start_date: November 18 2024 end_date: November 22 2024 - location: Durham, UK + city: Durham + country: United Kingdom type: workshop - title: Lean Tutorial url: https://www.dmg.tuwien.ac.at/lean2024/ start_date: September 18 2024 end_date: September 20 2024 - location: Vienna, Austria + city: Vienna + country: Austria type: tutorial - title: Interactive Theorem Proving 2024 url: https://www.viam.science.tsu.ge/itp2024/ start_date: September 9 2024 end_date: September 14 2024 - location: Tblisi, Georgia + city: Tbilisi + country: Georgia type: conference - title: "Interactions Between Proof Assistants and Mathematical Software, ICMS 2024" - location: Durham, UK + city: Durham + country: United Kingdom type: conference url: https://proof-assistants-and-software-icms2024.github.io/ start_date: July 22 2024 @@ -182,7 +198,8 @@ end_date: January 12 2024 - title: "Computer-verified proofs: 48 hours in Rome" - location: Rome, Italy + city: Rome + country: Italy url: https://www.mat.uniroma2.it/butterley/formalisation/ start_date: January 24 2024 end_date: January 26 2024 @@ -192,70 +209,83 @@ url: https://mizar.uwb.edu.pl/ITP2023/ start_date: July 31 2023 end_date: August 4 2023 - location: Bialystok, Poland + city: Bialystok + country: Poland type: conference - title: Conference on Intelligent Computer Mathematics 2023 url: https://cicm-conference.org/2023/cicm.php start_date: September 4 2023 end_date: September 8 2023 - location: Cambridge, UK + city: Cambridge + country: United Kingdom type: conference - title: Conference on Intelligent Computer Mathematics 2024 url: https://cicm-conference.org/2024/cicm.php start_date: August 5 2024 end_date: August 9 2024 - location: Montréal, Québec, Canada + city: Montréal + state: Québec + country: Canada type: conference - title: Conference on Intelligent Computer Mathematics 2025 url: https://cicm-conference.org/2025/cicm.php start_date: October 6 2025 end_date: October 11 2025 - location: Brasilia, Brazil + city: Brasilia + country: Brazil type: conference - title: Certified Programs and Proofs 2023 url: https://popl23.sigplan.org/home/CPP-2023 start_date: January 16 2023 end_date: January 17 2023 - location: Boston, MA, USA + city: Boston + state: Massachusetts + country: USA type: conference - title: Certified Programs and Proofs 2024 url: https://popl24.sigplan.org/home/CPP-2024 start_date: January 15 2024 end_date: January 16 2024 - location: London, UK + city: London + country: United Kingdom type: conference - title: Certified Programs and Proofs 2025 url: https://popl25.sigplan.org/home/CPP-2025 start_date: January 20 2025 end_date: January 21 2025 - location: Denver, CO, USA + city: Denver + state: Colorado + country: USA type: conference - title: Certified Programs and Proofs 2026 url: https://popl26.sigplan.org/home/CPP-2026 start_date: January 12 2026 end_date: January 13 2026 - location: Rennes, France + city: Rennes + country: France type: conference - title: Interactions of Proof Assistants and Mathematics url: https://itp-school-2023.github.io/ start_date: September 18 2023 end_date: September 29 2023 - location: Regensburg, Germany + city: Regensburg + country: Germany type: tutorial - title: Formal Mathematics and Computer-Assisted Proving url: https://www.hsm.uni-bonn.de/events/hsm-schools/formal2023/description/ start_date: September 18 2023 end_date: September 22 2023 - location: Bonn, Germany + city: Bonn + country: Germany type: tutorial - title: Learning Mathematics with Lean - 2 @@ -269,14 +299,16 @@ url: https://events.ilds.ro/autumnschool2023/ start_date: September 18 2023 end_date: September 20 2023 - location: Bucharest, Romania + city: Bucharest + country: Romania type: tutorial - title: Machine-Checked Mathematics url: https://www.lorentzcenter.nl/machine-checked-mathematics.html start_date: July 10 2023 end_date: July 14 2023 - location: Leiden, the Netherlands + city: Leiden + country: Netherlands type: workshop - title: Formalising algebraic geometry @@ -288,20 +320,23 @@ - title: Summer School about proof assistants for teaching proof and proving (PAT 2023) url: https://pat2023.icube.unistra.fr/ - location: Val d'Ajol, France + city: Val d'Ajol + country: France start_date: June 18 2023 end_date: June 23 2023 type: tutorial - title: Lean for the Curious Mathematician 2023 url: https://lftcm2023.github.io/tutorial - location: Düsseldorf, Germany + city: Düsseldorf + country: Germany start_date: September 4 2023 end_date: September 7 2023 type: tutorial - title: Lean for the Curious Mathematician 2023 – Colloquium - location: Düsseldorf, Germany + city: Düsseldorf + country: Germany url: https://lftcm2023.github.io/colloquium start_date: September 7 2023 end_date: September 8 2023 @@ -309,49 +344,63 @@ - title: Atelier Lean of the seventh mini symposium of the Roman Number Theory Association url: http://www.rnta.eu/7MSRNTA/registrationLEAN.html - location: Università Roma Tre, Rome, Italy + venue: Università Roma Tre + city: Rome + country: Italy start_date: May 2 2023 end_date: May 3 2023 type: tutorial - title: Lean for the Curious Mathematician 2024 url: https://conferences.cirm-math.fr/2970.html - location: Centre international de rencontres mathématiques (CIRM), Luminy, France + venue: CIRM + city: Luminy + country: France start_date: March 25 2024 end_date: March 29 2024 type: tutorial - title: "Formalisation of Mathematics: Workshop for Women and Mathematicians of Minority Gender" url: https://www.icms.org.uk/ - location: International Centre for Mathematical Sciences (ICMS), Edinburgh, United Kingdom + venue: ICMS + city: Edinburgh + country: United Kingdom start_date: May 27 2024 end_date: May 31 2024 type: tutorial - title: Formalisation of mathematics url: https://www.math.ku.dk/english/calendar/events/formalisation-of-mathematics/ - location: University of Copenhagen, Denmark + venue: University of Copenhagen + city: Copenhagen + country: Denmark start_date: June 26 2023 end_date: June 30 2023 type: tutorial - title: Formalization of mathematics url: https://www.msri.org/summer_schools/1021 - location: MSRI, Berkeley, USA + venue: MSRI + city: Berkeley + country: USA start_date: June 5 2023 end_date: June 16 2023 type: tutorial - title: Formal Languages, AI and Mathematics url: https://www.ihp.fr/fr/agenda/conference-flaim-formal-languages-ai-and-mathematics - location: IHP, Paris, France + venue: IHP + city: Paris + country: France start_date: November 3 2022 end_date: November 5 2022 type: conference - title: Prospects of formal mathematics url: https://www.him.uni-bonn.de/programs/future-programs/future-trimester-programs/prospects-of-formal-mathematics/description/ - location: HIM, Bonn, Germany + venue: HIM + city: Bonn + country: Germany start_date: May 6 2024 end_date: August 16 2024 type: conference @@ -360,26 +409,33 @@ url: https://www.birs.ca/events/2023/5-day-workshops/23w5124 start_date: May 21 2023 end_date: May 26 2023 - location: BIRS, Banff, Alberta, Canada + venue: BIRS + city: Banff + state: Alberta + country: Canada type: workshop - title: Machine Assisted Proofs url: http://www.ipam.ucla.edu/programs/workshops/machine-assisted-proofs/ - location: IPAM. Los Angeles + venue: IPAM + city: Los Angeles + country: USA start_date: February 13 2023 end_date: February 17 2023 type: workshop - title: Conference on Intelligent Computer Mathematics 2022 url: https://cicm-conference.org/2022/cicm.php - location: Tbilisi, Georgia + city: Tbilisi + country: Georgia start_date: September 19 2022 end_date: September 23 2022 type: conference - title: Interactive Theorem Proving 2022 url: https://itpconference.github.io/ITP22/ - location: Haifa, Israel + city: Haifa + country: Israel start_date: August 7 2022 end_date: August 10 2022 type: conference @@ -388,21 +444,26 @@ url: https://icerm.brown.edu/topical_workshops/tw-22-lean/ start_date: July 11 2022 end_date: July 15 2022 - location: ICERM, Providence, RI, USA + venue: ICERM + city: Providence + state: Rhode Island + country: USA type: tutorial - title: LeaN in LyoN url: https://www.univ-st-etienne.fr/lean-in-lyon.html start_date: May 10 2022 end_date: May 10 2022 - location: Lyon, France + city: Lyon + country: France type: workshop - title: Learning Mathematics with Lean url: https://www.lboro.ac.uk/departments/mec/events/2022/learningmathematicswithlean/ start_date: April 6 2022 end_date: April 6 2022 - location: Loughborough, UK and virtual + city: Loughborough + country: United Kingdom type: workshop - title: Fields Institute MathEd Forum @@ -421,7 +482,9 @@ - title: Certified Programs and Proofs 2022 url: https://popl22.sigplan.org/home/CPP-2022 - location: Philadelphia, PA, USA + city: Philadelphia + state: Pennsylvania + country: USA start_date: January 17 2022 end_date: January 18 2022 type: conference @@ -463,28 +526,33 @@ - title: Formal Methods in Mathematics / Lean Together 2020 url: https://www.andrew.cmu.edu/user/avigad/meetings/fomm2020/ - location: Pittsburgh, PA, USA + city: Pittsburgh + state: Pennsylvania + country: USA start_date: January 6 2020 end_date: January 10 2020 type: workshop - title: Lean Together 2019 url: https://lean-forward.github.io/lean-together/2019/ - location: Amsterdam, NL + city: Amsterdam + country: Netherlands start_date: January 7 2019 end_date: January 11 2019 type: workshop - title: Big Proof url: https://www.newton.ac.uk/event/bpr/ - location: Cambridge, UK + city: Cambridge + country: United Kingdom start_date: June 26 2017 end_date: August 4 2017 type: workshop - title: Big Proof url: https://www.newton.ac.uk/event/bprw03/ - location: Cambridge, UK + city: Cambridge + country: United Kingdom start_date: June 9 2025 end_date: June 13 2025 type: workshop @@ -497,7 +565,6 @@ end_date: January 17 2025 - title: "Leaning In! 2025" - location: Berlin, Germany city: Berlin country: Germany type: workshop From a40dd0e9313117a066286b3933e5da76a78520ce Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 13:55:08 +0100 Subject: [PATCH 04/18] Add support for hybrid events with MixedEventAttendanceMode Add hybrid event support to distinguish events that offer both in-person and virtual attendance options. Changes: - Add 'hybrid: bool' field to Event dataclass - Add validation: hybrid events must have city and country - Update schema.org generation for MixedEventAttendanceMode - Location for hybrid events is an array containing both: - Place with PostalAddress (physical location) - VirtualLocation (online access) - Mark 'Learning Mathematics with Lean' as hybrid event The schema.org location field now properly represents three modes: - OnlineEventAttendanceMode: VirtualLocation only - OfflineEventAttendanceMode: Place with PostalAddress only - MixedEventAttendanceMode: Array with both Place and VirtualLocation All 70 events pass validation (100%). --- data/events.yaml | 1 + make_site.py | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/data/events.yaml b/data/events.yaml index e5a41f363b..691a45001e 100644 --- a/data/events.yaml +++ b/data/events.yaml @@ -464,6 +464,7 @@ end_date: April 6 2022 city: Loughborough country: United Kingdom + hybrid: true type: workshop - title: Fields Institute MathEd Forum diff --git a/make_site.py b/make_site.py index e1d27974bd..303e759ed8 100755 --- a/make_site.py +++ b/make_site.py @@ -301,6 +301,7 @@ class Event: country: Optional[str] = None state: Optional[str] = None venue: Optional[str] = None + hybrid: bool = False def compute_location(self) -> str: """Compute location string from structured fields.""" @@ -327,6 +328,14 @@ def compute_location(self) -> str: else: return 'TBA' + def validate(self) -> None: + """Validate event data consistency.""" + if self.hybrid: + if not self.city or not self.country: + raise ValueError( + f"Hybrid event '{self.title}' must have both city and country fields" + ) + def generate_schema_org_json(event: Event) -> str: """Generate schema.org JSON-LD for an event.""" try: @@ -350,14 +359,43 @@ def generate_schema_org_json(event: Event) -> str: "endDate": end_date_iso, } - # Add location - determine if virtual or physical - if event.location.lower() in ['virtual', 'online']: + # Add location - determine if virtual, hybrid, or physical + if event.hybrid: + # Hybrid event: both physical and virtual attendance + schema_data["eventAttendanceMode"] = "https://schema.org/MixedEventAttendanceMode" + + # Build physical location + address = { + "@type": "PostalAddress", + "addressLocality": event.city, + "addressCountry": event.country + } + if event.state: + address["addressRegion"] = event.state + + place_name = event.venue if event.venue else event.city + + # Location is an array with both Place and VirtualLocation + schema_data["location"] = [ + { + "@type": "Place", + "name": place_name, + "address": address + }, + { + "@type": "VirtualLocation", + "url": event.url + } + ] + elif event.location.lower() in ['virtual', 'online']: + # Purely virtual event schema_data["eventAttendanceMode"] = "https://schema.org/OnlineEventAttendanceMode" schema_data["location"] = { "@type": "VirtualLocation", "url": event.url } else: + # Physical event only schema_data["eventAttendanceMode"] = "https://schema.org/OfflineEventAttendanceMode" # Use structured address data if available, otherwise fall back to location string @@ -651,6 +689,8 @@ def format_date_range(event): # Compute location from structured fields if not explicitly provided if not e.location or e.location == '': e.location = e.compute_location() + # Validate event data consistency + e.validate() e.date_range = format_date_range(e) e.schema_org_json = generate_schema_org_json(e) From 3aaa95bd55a41ce254fc5c4f36ba33270d97573f Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:07:09 +0100 Subject: [PATCH 05/18] Use ISO 3166-1 alpha-2 country codes in event location data Update addressCountry values to use standard two-letter country codes (e.g., US, GB, DE) instead of full country names for better machine readability and compliance with schema.org recommendations. --- data/events.yaml | 116 +++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/data/events.yaml b/data/events.yaml index 691a45001e..311aa74559 100644 --- a/data/events.yaml +++ b/data/events.yaml @@ -3,7 +3,7 @@ start_date: December 9 2025 end_date: December 12 2025 city: Bologna - country: Italy + country: IT type: conference - title: "Lean Together 2026" @@ -19,7 +19,7 @@ end_date: March 12 2026 venue: Spielfeld city: Berlin - country: Germany + country: DE type: conference - title: Techniques and Tools for the Formalization of Analysis @@ -29,7 +29,7 @@ venue: ICERM city: Providence state: Rhode Island - country: USA + country: US type: workshop - title: Proof assistant users meetup in Ghent @@ -37,7 +37,7 @@ start_date: October 27 2025 end_date: October 27 2025 city: Ghent - country: Belgium + country: BE type: workshop - title: Lean for the Curious Mathematician 2026 (Italy) @@ -46,7 +46,7 @@ end_date: September 11 2026 venue: SNS city: Cortona - country: Italy + country: IT type: workshop - title: Formalising Algebraic Geometry in Lean @@ -54,7 +54,7 @@ start_date: November 19 2025 end_date: November 21 2025 city: Heidelberg - country: Germany + country: DE type: workshop - title: Lean for PDEs @@ -63,7 +63,7 @@ end_date: October 9 2025 city: Berkeley state: California - country: USA + country: US type: workshop - title: "VSTTE 2025: Conference on Verified Software: Theories, Tools, and Experiments" @@ -71,7 +71,7 @@ start_date: October 6 2025 end_date: October 7 2025 city: Menlo Park - country: USA + country: US type: conference - title: EuroProofNet final symposium @@ -79,7 +79,7 @@ start_date: September 8 2025 end_date: September 19 2025 city: Orsay - country: France + country: FR type: conference - title: Mechanization and Mathematical Research @@ -87,7 +87,7 @@ start_date: September 15 2025 end_date: September 19 2025 city: Leiden - country: Netherlands + country: NL type: workshop - title: Summer School on Formalizing Mathematics in Lean @@ -95,7 +95,7 @@ start_date: July 21 2025 end_date: July 25 2025 city: Utrecht - country: Netherlands + country: NL type: tutorial - title: Lean for Mathematicians @@ -104,7 +104,7 @@ end_date: June 27 2025 city: New York state: New York - country: USA + country: US type: tutorial - title: Formalizing Class Field Theory @@ -112,7 +112,7 @@ start_date: July 21 2025 end_date: July 25 2025 city: Oxford - country: United Kingdom + country: GB type: workshop - title: Solving riddles with Lean @@ -120,7 +120,7 @@ start_date: July 17 2025 end_date: July 17 2025 city: Ghent - country: Belgium + country: BE type: workshop - title: Lean for the Curious Mathematician (India) @@ -129,7 +129,7 @@ end_date: April 27 2025 venue: ICTS city: Bengaluru - country: India + country: IN type: workshop - title: Autoformalization for the Working Mathematician @@ -138,7 +138,7 @@ end_date: April 27 2025 city: Providence state: Rhode Island - country: USA + country: US type: workshop - title: Interactive Theorem Proving 2025 @@ -146,7 +146,7 @@ start_date: September 27 2025 end_date: October 3 2025 city: Reykjavik - country: Iceland + country: IS type: conference - title: AI for Mathematics and Theoretical Computer Science @@ -155,7 +155,7 @@ end_date: April 11 2025 city: Berkeley state: California - country: USA + country: US type: workshop - title: Computational Algebraic Geometry Workshop @@ -163,7 +163,7 @@ start_date: November 18 2024 end_date: November 22 2024 city: Durham - country: United Kingdom + country: GB type: workshop - title: Lean Tutorial @@ -171,7 +171,7 @@ start_date: September 18 2024 end_date: September 20 2024 city: Vienna - country: Austria + country: AT type: tutorial - title: Interactive Theorem Proving 2024 @@ -179,12 +179,12 @@ start_date: September 9 2024 end_date: September 14 2024 city: Tbilisi - country: Georgia + country: GE type: conference - title: "Interactions Between Proof Assistants and Mathematical Software, ICMS 2024" city: Durham - country: United Kingdom + country: GB type: conference url: https://proof-assistants-and-software-icms2024.github.io/ start_date: July 22 2024 @@ -199,7 +199,7 @@ - title: "Computer-verified proofs: 48 hours in Rome" city: Rome - country: Italy + country: IT url: https://www.mat.uniroma2.it/butterley/formalisation/ start_date: January 24 2024 end_date: January 26 2024 @@ -210,7 +210,7 @@ start_date: July 31 2023 end_date: August 4 2023 city: Bialystok - country: Poland + country: PL type: conference - title: Conference on Intelligent Computer Mathematics 2023 @@ -218,7 +218,7 @@ start_date: September 4 2023 end_date: September 8 2023 city: Cambridge - country: United Kingdom + country: GB type: conference - title: Conference on Intelligent Computer Mathematics 2024 @@ -227,7 +227,7 @@ end_date: August 9 2024 city: Montréal state: Québec - country: Canada + country: CA type: conference - title: Conference on Intelligent Computer Mathematics 2025 @@ -235,7 +235,7 @@ start_date: October 6 2025 end_date: October 11 2025 city: Brasilia - country: Brazil + country: BR type: conference - title: Certified Programs and Proofs 2023 @@ -244,7 +244,7 @@ end_date: January 17 2023 city: Boston state: Massachusetts - country: USA + country: US type: conference - title: Certified Programs and Proofs 2024 @@ -252,7 +252,7 @@ start_date: January 15 2024 end_date: January 16 2024 city: London - country: United Kingdom + country: GB type: conference - title: Certified Programs and Proofs 2025 @@ -261,7 +261,7 @@ end_date: January 21 2025 city: Denver state: Colorado - country: USA + country: US type: conference - title: Certified Programs and Proofs 2026 @@ -269,7 +269,7 @@ start_date: January 12 2026 end_date: January 13 2026 city: Rennes - country: France + country: FR type: conference - title: Interactions of Proof Assistants and Mathematics @@ -277,7 +277,7 @@ start_date: September 18 2023 end_date: September 29 2023 city: Regensburg - country: Germany + country: DE type: tutorial - title: Formal Mathematics and Computer-Assisted Proving @@ -285,7 +285,7 @@ start_date: September 18 2023 end_date: September 22 2023 city: Bonn - country: Germany + country: DE type: tutorial - title: Learning Mathematics with Lean - 2 @@ -300,7 +300,7 @@ start_date: September 18 2023 end_date: September 20 2023 city: Bucharest - country: Romania + country: RO type: tutorial - title: Machine-Checked Mathematics @@ -308,7 +308,7 @@ start_date: July 10 2023 end_date: July 14 2023 city: Leiden - country: Netherlands + country: NL type: workshop - title: Formalising algebraic geometry @@ -321,7 +321,7 @@ - title: Summer School about proof assistants for teaching proof and proving (PAT 2023) url: https://pat2023.icube.unistra.fr/ city: Val d'Ajol - country: France + country: FR start_date: June 18 2023 end_date: June 23 2023 type: tutorial @@ -329,14 +329,14 @@ - title: Lean for the Curious Mathematician 2023 url: https://lftcm2023.github.io/tutorial city: Düsseldorf - country: Germany + country: DE start_date: September 4 2023 end_date: September 7 2023 type: tutorial - title: Lean for the Curious Mathematician 2023 – Colloquium city: Düsseldorf - country: Germany + country: DE url: https://lftcm2023.github.io/colloquium start_date: September 7 2023 end_date: September 8 2023 @@ -346,7 +346,7 @@ url: http://www.rnta.eu/7MSRNTA/registrationLEAN.html venue: Università Roma Tre city: Rome - country: Italy + country: IT start_date: May 2 2023 end_date: May 3 2023 type: tutorial @@ -355,7 +355,7 @@ url: https://conferences.cirm-math.fr/2970.html venue: CIRM city: Luminy - country: France + country: FR start_date: March 25 2024 end_date: March 29 2024 type: tutorial @@ -364,7 +364,7 @@ url: https://www.icms.org.uk/ venue: ICMS city: Edinburgh - country: United Kingdom + country: GB start_date: May 27 2024 end_date: May 31 2024 type: tutorial @@ -373,7 +373,7 @@ url: https://www.math.ku.dk/english/calendar/events/formalisation-of-mathematics/ venue: University of Copenhagen city: Copenhagen - country: Denmark + country: DK start_date: June 26 2023 end_date: June 30 2023 type: tutorial @@ -382,7 +382,7 @@ url: https://www.msri.org/summer_schools/1021 venue: MSRI city: Berkeley - country: USA + country: US start_date: June 5 2023 end_date: June 16 2023 type: tutorial @@ -391,7 +391,7 @@ url: https://www.ihp.fr/fr/agenda/conference-flaim-formal-languages-ai-and-mathematics venue: IHP city: Paris - country: France + country: FR start_date: November 3 2022 end_date: November 5 2022 type: conference @@ -400,7 +400,7 @@ url: https://www.him.uni-bonn.de/programs/future-programs/future-trimester-programs/prospects-of-formal-mathematics/description/ venue: HIM city: Bonn - country: Germany + country: DE start_date: May 6 2024 end_date: August 16 2024 type: conference @@ -412,14 +412,14 @@ venue: BIRS city: Banff state: Alberta - country: Canada + country: CA type: workshop - title: Machine Assisted Proofs url: http://www.ipam.ucla.edu/programs/workshops/machine-assisted-proofs/ venue: IPAM city: Los Angeles - country: USA + country: US start_date: February 13 2023 end_date: February 17 2023 type: workshop @@ -427,7 +427,7 @@ - title: Conference on Intelligent Computer Mathematics 2022 url: https://cicm-conference.org/2022/cicm.php city: Tbilisi - country: Georgia + country: GE start_date: September 19 2022 end_date: September 23 2022 type: conference @@ -435,7 +435,7 @@ - title: Interactive Theorem Proving 2022 url: https://itpconference.github.io/ITP22/ city: Haifa - country: Israel + country: IL start_date: August 7 2022 end_date: August 10 2022 type: conference @@ -447,7 +447,7 @@ venue: ICERM city: Providence state: Rhode Island - country: USA + country: US type: tutorial - title: LeaN in LyoN @@ -455,7 +455,7 @@ start_date: May 10 2022 end_date: May 10 2022 city: Lyon - country: France + country: FR type: workshop - title: Learning Mathematics with Lean @@ -463,7 +463,7 @@ start_date: April 6 2022 end_date: April 6 2022 city: Loughborough - country: United Kingdom + country: GB hybrid: true type: workshop @@ -485,7 +485,7 @@ url: https://popl22.sigplan.org/home/CPP-2022 city: Philadelphia state: Pennsylvania - country: USA + country: US start_date: January 17 2022 end_date: January 18 2022 type: conference @@ -529,7 +529,7 @@ url: https://www.andrew.cmu.edu/user/avigad/meetings/fomm2020/ city: Pittsburgh state: Pennsylvania - country: USA + country: US start_date: January 6 2020 end_date: January 10 2020 type: workshop @@ -537,7 +537,7 @@ - title: Lean Together 2019 url: https://lean-forward.github.io/lean-together/2019/ city: Amsterdam - country: Netherlands + country: NL start_date: January 7 2019 end_date: January 11 2019 type: workshop @@ -545,7 +545,7 @@ - title: Big Proof url: https://www.newton.ac.uk/event/bpr/ city: Cambridge - country: United Kingdom + country: GB start_date: June 26 2017 end_date: August 4 2017 type: workshop @@ -553,7 +553,7 @@ - title: Big Proof url: https://www.newton.ac.uk/event/bprw03/ city: Cambridge - country: United Kingdom + country: GB start_date: June 9 2025 end_date: June 13 2025 type: workshop @@ -567,7 +567,7 @@ - title: "Leaning In! 2025" city: Berlin - country: Germany + country: DE type: workshop url: https://leaning.in start_date: March 13 2025 From 545c9c81773d9d13a8a841ec8572ccec3960801f Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:19:13 +0100 Subject: [PATCH 06/18] Remove redundant description field and fix NODOWNLOAD behavior - Remove duplicate description field from event JSON-LD (was just repeating the title) - Fix Formalization class to respect NODOWNLOAD environment variable - Prevents GitHub API rate limiting during local development with NODOWNLOAD=1 --- make_site.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/make_site.py b/make_site.py index 303e759ed8..8dfc9af4f2 100755 --- a/make_site.py +++ b/make_site.py @@ -143,10 +143,14 @@ class Formalization: @cached_property def github_repo(self): - return github.get_repo(self.organization + '/' + self.repo) + if DOWNLOAD: + return github.get_repo(self.organization + '/' + self.repo) + return None @property def stars(self): + if not DOWNLOAD or self.github_repo is None: + return 0 return self.github_repo.stargazers_count with (DATA/'formalizations.yaml').open('r', encoding='utf-8') as f_file: @@ -353,7 +357,6 @@ def generate_schema_org_json(event: Event) -> str: "@context": "https://schema.org", "@type": "Event", "name": event.title, - "description": event.title, "url": event.url, "startDate": start_date_iso, "endDate": end_date_iso, From db8e10d8c09bccb37ae052c1889bab90b268cfc1 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:30:37 +0100 Subject: [PATCH 07/18] Simplify Node.js setup in GitHub Actions workflow Move Node.js and npm setup earlier in the workflow and remove conditional checks. This makes the workflow simpler and allows validation to run as a standard part of the build process rather than an optional step. Changes: - Move setup-node action to run right after Python setup - Move npm ci to run before build step - Remove conditional checks from Node.js setup and validation steps - Simplify validation step to just run npm command - Use version tag (v4.1.0) instead of commit hash for setup-node action --- .github/workflows/build.yml | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ede6ea097c..47eb8ac31a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,11 @@ jobs: # TODO: fix things so we can build with 3.12 and above python-version: 3.11 + - name: setup Node.js + uses: actions/setup-node@v4.1.0 + with: + node-version: '24' + - name: install bibtool run: | sudo apt-get update --fix-missing @@ -40,6 +45,9 @@ jobs: - name: install Python dependencies run: python -m pip install --upgrade pip -r requirements.txt + - name: install Node.js dependencies + run: npm ci + - name: build and deploy id: build run: | @@ -52,22 +60,8 @@ jobs: github_ref: ${{ github.ref }} ZULIP_KEY: ${{ secrets.ZULIP_KEY }} - - name: setup Node.js - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: '24' - - - name: install Node.js dependencies - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - run: npm ci - - name: validate semantic data in events.html - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - run: | - echo "Validating schema.org Event markup in events.html..." - npm run validate:events - echo "✓ Semantic data validation passed!" + run: npm run validate:events - name: Upload artifact id: upload-artifact From 92a34c729a5227128fc08a2ca29b8ff89bebd8f6 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:30:43 +0100 Subject: [PATCH 08/18] Add is_fully_remote method and validation for Event class Introduce a is_fully_remote() method to centralize the logic for detecting virtual/online events, replacing duplicate inline checks throughout the code. Also extend validation to ensure fully remote events don't have physical location fields (city, state, country), maintaining data consistency. Changes: - Add Event.is_fully_remote() method - Update compute_location() to use new method - Update generate_schema_org_json() to use new method - Add validation check for fully remote events --- make_site.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/make_site.py b/make_site.py index 8dfc9af4f2..a71594897f 100755 --- a/make_site.py +++ b/make_site.py @@ -307,10 +307,14 @@ class Event: venue: Optional[str] = None hybrid: bool = False + def is_fully_remote(self) -> bool: + """Check if this is a fully remote/virtual event.""" + return self.location.lower() in ['virtual', 'online'] + def compute_location(self) -> str: """Compute location string from structured fields.""" # For virtual events - if self.location.lower() in ['virtual', 'online']: + if self.is_fully_remote(): return self.location # Build location from structured fields @@ -340,6 +344,12 @@ def validate(self) -> None: f"Hybrid event '{self.title}' must have both city and country fields" ) + if self.is_fully_remote(): + if self.city or self.state or self.country: + raise ValueError( + f"Fully remote event '{self.title}' should not have city, state, or country fields" + ) + def generate_schema_org_json(event: Event) -> str: """Generate schema.org JSON-LD for an event.""" try: @@ -390,7 +400,7 @@ def generate_schema_org_json(event: Event) -> str: "url": event.url } ] - elif event.location.lower() in ['virtual', 'online']: + elif event.is_fully_remote(): # Purely virtual event schema_data["eventAttendanceMode"] = "https://schema.org/OnlineEventAttendanceMode" schema_data["location"] = { From f6d1c7766056606778d4f48e813f651c1a765197 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:40:21 +0100 Subject: [PATCH 09/18] Make date parsing errors explicit in schema.org generation Change generate_schema_org_json to throw ValueError exceptions with helpful error messages instead of silently returning empty strings when dates cannot be parsed. This makes debugging easier and ensures all events have valid dates. Changes: - Combine date parsing and ISO 8601 formatting into single lines - Use separate try/except blocks for start and end dates - Raise ValueError with specific error messages indicating which event and which date field is invalid --- make_site.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/make_site.py b/make_site.py index a71594897f..8a85927660 100755 --- a/make_site.py +++ b/make_site.py @@ -352,15 +352,16 @@ def validate(self) -> None: def generate_schema_org_json(event: Event) -> str: """Generate schema.org JSON-LD for an event.""" + # Parse dates to ISO 8601 format try: - # Parse dates to ISO 8601 format - start_date_obj = datetime.strptime(event.start_date, '%B %d %Y') - start_date_iso = start_date_obj.strftime('%Y-%m-%d') - end_date_obj = datetime.strptime(event.end_date, '%B %d %Y') - end_date_iso = end_date_obj.strftime('%Y-%m-%d') + start_date_iso = datetime.strptime(event.start_date, '%B %d %Y').strftime('%Y-%m-%d') except (ValueError, TypeError, AttributeError): - # If we can't parse the dates, don't generate schema.org data - return '' + raise ValueError(f"Invalid start date for event '{event.title}': {event.start_date}") + + try: + end_date_iso = datetime.strptime(event.end_date, '%B %d %Y').strftime('%Y-%m-%d') + except (ValueError, TypeError, AttributeError): + raise ValueError(f"Invalid end date for event '{event.title}': {event.end_date}") # Build the schema.org structure schema_data = { From 9d2f3802ba1df69f4eb4524d11b5d17747b697e3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:41:23 +0000 Subject: [PATCH 10/18] Initial plan From 24ef5597be220a55f196979c88288d400a99977d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:43:19 +0000 Subject: [PATCH 11/18] Use human-readable version v4.1.0 for actions/setup-node Co-authored-by: jessealama <56691+jessealama@users.noreply.github.com> --- .github/workflows/build_pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 9a393efb12..2c2a624b8c 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -41,7 +41,7 @@ jobs: - name: setup Node.js if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@v4.1.0 with: node-version: '24' From 2f6efcfa979f7e35699140f5c712d4e68c8e06d9 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:48:21 +0100 Subject: [PATCH 12/18] Update .github/workflows/build_pr.yml --- .github/workflows/build_pr.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 2c2a624b8c..86737c9687 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -52,9 +52,7 @@ jobs: - name: validate semantic data in events.html if: ${{ !cancelled() && (steps.build.outcome == 'success') }} run: | - echo "Validating schema.org Event markup in events.html..." npm run validate:events - echo "✓ Semantic data validation passed!" - name: Upload artifact id: upload-artifact From 2e0229ea0c3aa8700d92ef2a14b861439ac1a420 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:51:32 +0100 Subject: [PATCH 13/18] Simplify validation step to single-line format in build_pr.yml --- .github/workflows/build_pr.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 86737c9687..24711dd62a 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -51,8 +51,7 @@ jobs: - name: validate semantic data in events.html if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - run: | - npm run validate:events + run: npm run validate:events - name: Upload artifact id: upload-artifact From 659d8326ab0a953846553d93ac9ba4ca3b396f6a Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 14:56:56 +0100 Subject: [PATCH 14/18] Simplify package.json to focus on CI/CD dependencies --- package.json | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index b3bbdd0391..e0760ec424 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,13 @@ { "name": "leanprover-community.github.io", - "version": "1.0.0", - "description": "The deployed website lives on the `master` branch of this repository. To make changes to the website, please fork the repository and make a PR against the [`lean4`](https://github.com/leanprover-community/leanprover-community.github.io/tree/lean4) branch. Once your PR is merged, CI will automatically deploy the changes to the `master` branch.", - "main": "index.js", + "description": "This file is used primarily for pulling in npm packages needed for CI/CD validation tasks.", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", "validate:events": "sdtt --file build/events.html --schemas Event" }, "repository": { "type": "git", - "url": "git+https://github.com/jessealama/leanprover-community.github.io.git" + "url": "git+https://github.com/leanprover-community/leanprover-community.github.io.git" }, - "keywords": [], - "author": "", - "license": "ISC", - "type": "commonjs", - "bugs": { - "url": "https://github.com/jessealama/leanprover-community.github.io/issues" - }, - "homepage": "https://github.com/jessealama/leanprover-community.github.io#readme", "devDependencies": { "structured-data-testing-tool": "4.5.0" } From 22ba98e57cb9c0fbfa06077dbc6b03883538cec7 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 15:04:21 +0100 Subject: [PATCH 15/18] Use pickle cache for project data when NODOWNLOAD is set --- make_site.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/make_site.py b/make_site.py index 8a85927660..5f1db54547 100755 --- a/make_site.py +++ b/make_site.py @@ -726,7 +726,7 @@ class Project: oprojects_3 = yaml.safe_load(h_file) pkl_dump('oprojects_3', oprojects_3) else: - oprojects_3 = {} # Use empty dict when not downloading + oprojects_3 = pkl_load('oprojects_3', {}) projects_3 = [] @@ -739,7 +739,8 @@ class Project: projects_3.append(Project(name, project['organization'], descr, project['maintainers'], stars, github_repo.html_url)) projects_3.sort(key = lambda p: p.stars, reverse=True) pkl_dump('projects_3', projects_3) -# else: projects_3 stays as empty list [] +else: + projects_3 = pkl_load('projects_3', []) if DOWNLOAD: download( @@ -749,7 +750,7 @@ class Project: oprojects_4 = yaml.safe_load(h_file) pkl_dump('oprojects_4', oprojects_4) else: - oprojects_4 = [] # Use empty list when not downloading + oprojects_4 = pkl_load('oprojects_4', []) projects_4 = [] @@ -763,7 +764,8 @@ class Project: projects_4.append(Project(name, github_repo.owner.login, descr, None, stars, github_repo.html_url)) projects_4.sort(key = lambda p: p.stars, reverse=True) pkl_dump('projects_4', projects_4) -# else: projects_4 stays as empty list [] +else: + projects_4 = pkl_load('projects_4', []) if DOWNLOAD: # We used to use this count but it didn't include mathlib3 contributors From dbe8fd06176f459c521344fff07f8673645e8ee3 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Tue, 11 Nov 2025 15:05:42 +0100 Subject: [PATCH 16/18] Update actions/setup-node to v6 --- .github/workflows/build.yml | 2 +- .github/workflows/build_pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47eb8ac31a..e75f6ec105 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: python-version: 3.11 - name: setup Node.js - uses: actions/setup-node@v4.1.0 + uses: actions/setup-node@v6 with: node-version: '24' diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 24711dd62a..9177079e62 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -41,7 +41,7 @@ jobs: - name: setup Node.js if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - uses: actions/setup-node@v4.1.0 + uses: actions/setup-node@v6 with: node-version: '24' From 9e1644fc82cf54330f7917150daae7546dbe95d4 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Wed, 12 Nov 2025 11:07:40 +0100 Subject: [PATCH 17/18] Replace JavaScript sdtt with Python pydantic2-schemaorg for schema.org validation --- .github/workflows/build.yml | 11 - .github/workflows/build_pr.yml | 14 - make_site.py | 93 ++-- package-lock.json | 953 --------------------------------- package.json | 14 - requirements.txt | 1 + 6 files changed, 45 insertions(+), 1041 deletions(-) delete mode 100644 package-lock.json delete mode 100644 package.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e75f6ec105..256ffbee0a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,11 +32,6 @@ jobs: # TODO: fix things so we can build with 3.12 and above python-version: 3.11 - - name: setup Node.js - uses: actions/setup-node@v6 - with: - node-version: '24' - - name: install bibtool run: | sudo apt-get update --fix-missing @@ -45,9 +40,6 @@ jobs: - name: install Python dependencies run: python -m pip install --upgrade pip -r requirements.txt - - name: install Node.js dependencies - run: npm ci - - name: build and deploy id: build run: | @@ -60,9 +52,6 @@ jobs: github_ref: ${{ github.ref }} ZULIP_KEY: ${{ secrets.ZULIP_KEY }} - - name: validate semantic data in events.html - run: npm run validate:events - - name: Upload artifact id: upload-artifact if: ${{ !cancelled() && (steps.build.outcome == 'success') }} diff --git a/.github/workflows/build_pr.yml b/.github/workflows/build_pr.yml index 9177079e62..9332c22190 100644 --- a/.github/workflows/build_pr.yml +++ b/.github/workflows/build_pr.yml @@ -39,20 +39,6 @@ jobs: run: | ./make_site.py - - name: setup Node.js - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - uses: actions/setup-node@v6 - with: - node-version: '24' - - - name: install Node.js dependencies - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - run: npm ci - - - name: validate semantic data in events.html - if: ${{ !cancelled() && (steps.build.outcome == 'success') }} - run: npm run validate:events - - name: Upload artifact id: upload-artifact if: ${{ !cancelled() && (steps.build.outcome == 'success') }} diff --git a/make_site.py b/make_site.py index 5f1db54547..1ee7cd81c2 100755 --- a/make_site.py +++ b/make_site.py @@ -31,6 +31,11 @@ import zulip +from pydantic2_schemaorg.Event import Event as SchemaOrgEvent +from pydantic2_schemaorg.Place import Place +from pydantic2_schemaorg.PostalAddress import PostalAddress +from pydantic2_schemaorg.VirtualLocation import VirtualLocation + FilePath = Union[str, Path] DOWNLOAD = not 'NODOWNLOAD' in os.environ @@ -351,7 +356,7 @@ def validate(self) -> None: ) def generate_schema_org_json(event: Event) -> str: - """Generate schema.org JSON-LD for an event.""" + """Generate schema.org JSON-LD for an event using pydantic2-schemaorg models.""" # Parse dates to ISO 8601 format try: start_date_iso = datetime.strptime(event.start_date, '%B %d %Y').strftime('%Y-%m-%d') @@ -363,86 +368,76 @@ def generate_schema_org_json(event: Event) -> str: except (ValueError, TypeError, AttributeError): raise ValueError(f"Invalid end date for event '{event.title}': {event.end_date}") - # Build the schema.org structure - schema_data = { - "@context": "https://schema.org", - "@type": "Event", - "name": event.title, - "url": event.url, - "startDate": start_date_iso, - "endDate": end_date_iso, - } - - # Add location - determine if virtual, hybrid, or physical + # Build location - determine if virtual, hybrid, or physical + location = None + event_attendance_mode = None + if event.hybrid: # Hybrid event: both physical and virtual attendance - schema_data["eventAttendanceMode"] = "https://schema.org/MixedEventAttendanceMode" + event_attendance_mode = "https://schema.org/MixedEventAttendanceMode" # Build physical location - address = { - "@type": "PostalAddress", + address_kwargs = { "addressLocality": event.city, "addressCountry": event.country } if event.state: - address["addressRegion"] = event.state + address_kwargs["addressRegion"] = event.state place_name = event.venue if event.venue else event.city # Location is an array with both Place and VirtualLocation - schema_data["location"] = [ - { - "@type": "Place", - "name": place_name, - "address": address - }, - { - "@type": "VirtualLocation", - "url": event.url - } + location = [ + Place( + name=place_name, + address=PostalAddress(**address_kwargs) + ), + VirtualLocation(url=event.url) ] elif event.is_fully_remote(): # Purely virtual event - schema_data["eventAttendanceMode"] = "https://schema.org/OnlineEventAttendanceMode" - schema_data["location"] = { - "@type": "VirtualLocation", - "url": event.url - } + event_attendance_mode = "https://schema.org/OnlineEventAttendanceMode" + location = VirtualLocation(url=event.url) else: # Physical event only - schema_data["eventAttendanceMode"] = "https://schema.org/OfflineEventAttendanceMode" + event_attendance_mode = "https://schema.org/OfflineEventAttendanceMode" # Use structured address data if available, otherwise fall back to location string if event.city and event.country: - address = { - "@type": "PostalAddress", + address_kwargs = { "addressLocality": event.city, "addressCountry": event.country } # Add state/region for US addresses if available if event.state: - address["addressRegion"] = event.state + address_kwargs["addressRegion"] = event.state # Use venue as Place name if available, otherwise use city place_name = event.venue if event.venue else event.city - schema_data["location"] = { - "@type": "Place", - "name": place_name, - "address": address - } + location = Place( + name=place_name, + address=PostalAddress(**address_kwargs) + ) else: # Fall back to simple Place with just name - schema_data["location"] = { - "@type": "Place", - "name": event.location - } - - # Add event status - assume scheduled for future events - schema_data["eventStatus"] = "https://schema.org/EventScheduled" + location = Place(name=event.location) + + # Create the schema.org Event model - Pydantic will validate it + schema_event = SchemaOrgEvent( + name=event.title, + url=event.url, + startDate=start_date_iso, + endDate=end_date_iso, + location=location, + eventAttendanceMode=event_attendance_mode, + eventStatus="https://schema.org/EventScheduled" + ) - # Convert to pretty-printed JSON - return json.dumps(schema_data, indent=2) + # Convert to JSON-LD format with pretty printing and add @context + event_dict = json.loads(schema_event.json(exclude_none=True)) + event_dict["@context"] = "https://schema.org" + return json.dumps(event_dict, indent=2) @dataclass class Course: diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 6c4b94752c..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,953 +0,0 @@ -{ - "name": "leanprover-community.github.io", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "leanprover-community.github.io", - "version": "1.0.0", - "license": "ISC", - "devDependencies": { - "structured-data-testing-tool": "^4.5.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/columnify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", - "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-ansi": "^6.0.1", - "wcwidth": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==", - "dev": true, - "license": "BSD-like", - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true, - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", - "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==", - "dev": true, - "license": "MIT" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true, - "license": "ISC" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/structured-data-testing-tool": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/structured-data-testing-tool/-/structured-data-testing-tool-4.5.0.tgz", - "integrity": "sha512-EjNG7L4PllMkTPlfxpyrKT5X0ub3C3PZIqAsjSDVUlnhRE/A5zoNTEukIxYjYlv8LgH+aqxfS0XwczZosbJVew==", - "dev": true, - "license": "ISC", - "dependencies": { - "chalk": "^2.4.2", - "columnify": "^1.5.4", - "get-stream": "^5.1.0", - "is-stream": "^2.0.0", - "jmespath": "^0.15.0", - "node-fetch": "^2.6.0", - "validator": "^11.0.0", - "web-auto-extractor": "^1.0.17", - "yargs": "^13.2.4" - }, - "bin": { - "sdtt": "bin/cli.js" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/validator": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", - "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-auto-extractor": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/web-auto-extractor/-/web-auto-extractor-1.0.17.tgz", - "integrity": "sha512-V+ekXwPSD8c2FqZWpdxJ7P2fvlDbNiEgSdrp+pP5RTsUHOb4gzvfbdmG5ymd1b/6gtQ6seNPesqjZQ1DCMxIww==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-polyfill": "^6.8.0", - "cheerio": "^0.22.0", - "htmlparser2": "^3.9.1" - }, - "engines": { - "node": ">=4.4" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index e0760ec424..0000000000 --- a/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "leanprover-community.github.io", - "description": "This file is used primarily for pulling in npm packages needed for CI/CD validation tasks.", - "scripts": { - "validate:events": "sdtt --file build/events.html --schemas Event" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/leanprover-community/leanprover-community.github.io.git" - }, - "devDependencies": { - "structured-data-testing-tool": "4.5.0" - } -} diff --git a/requirements.txt b/requirements.txt index 7a93ae221c..396a19e383 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,3 +20,4 @@ ruamel.yaml>=0.17.10 html5lib>=1.1 python-slugify>=4.0.1 zulip>=0.9.0 +pydantic2-schemaorg>=0.3.0 From dd483ea4b9e55cd6f1aa24b4c9b02d89891d1a5c Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Wed, 12 Nov 2025 11:24:42 +0100 Subject: [PATCH 18/18] Add state field to all US events --- data/events.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/events.yaml b/data/events.yaml index 311aa74559..5f83d76ac7 100644 --- a/data/events.yaml +++ b/data/events.yaml @@ -71,6 +71,7 @@ start_date: October 6 2025 end_date: October 7 2025 city: Menlo Park + state: California country: US type: conference @@ -382,6 +383,7 @@ url: https://www.msri.org/summer_schools/1021 venue: MSRI city: Berkeley + state: California country: US start_date: June 5 2023 end_date: June 16 2023 @@ -419,6 +421,7 @@ url: http://www.ipam.ucla.edu/programs/workshops/machine-assisted-proofs/ venue: IPAM city: Los Angeles + state: California country: US start_date: February 13 2023 end_date: February 17 2023