diff --git a/website/src/components/BlogPostInfo.astro b/website/src/components/BlogPostInfo.astro index 8b5712bfee4c..ecc79e63344c 100755 --- a/website/src/components/BlogPostInfo.astro +++ b/website/src/components/BlogPostInfo.astro @@ -1,36 +1,63 @@ --- import "@src/styles/blog/index.scss"; +import { getEntry, type CollectionEntry } from "astro:content"; + export interface Props { - frontmatter: { - coauthorName?: string; - coauthorAvatar?: string; - authorName: string; - authorUrl?: string; - authorAvatar?: string; - pubDate: string; - }; + post: CollectionEntry<"blog">["data"]; +} + +async function getAuthorsData( + authors: CollectionEntry<"authors">["id"][] +): Promise[]> { + const authorsData = await Promise.all( + authors.map((author) => getEntry("authors", author)) + ); + return authorsData; } -const {coauthorName, coauthorAvatar, authorName, authorUrl, authorAvatar, pubDate} = Astro.props.frontmatter; +const { post } = Astro.props; +const authors = await getAuthorsData( + post.authors as CollectionEntry<"authors">["id"][] +); ---
-
- - - - {coauthorAvatar && } - - - {authorUrl ? {authorName} : {authorName}} + + { + authors.map(({ data: author }) => ( + + + + )) + } + - {coauthorName && & {coauthorName}} -
+
+ { + authors.map((author, index) => ( + <> + {author.data.url ? ( + + {author.data.name} + + ) : ( + {author.data.name} + )} + {authors.length > 1 && index + 1 == authors.length - 1 ? " & " : ""} + {authors.length > 1 && index + 1 < authors.length - 1 ? ", " : ""} + + )) + } +
- +
diff --git a/website/src/components/PostsList.astro b/website/src/components/PostsList.astro index c42a9d7296d6..f1e3a396f6c8 100644 --- a/website/src/components/PostsList.astro +++ b/website/src/components/PostsList.astro @@ -1,22 +1,32 @@ --- import InlineSVG from "@src/components/InlineSVG.astro"; import BlogPostInfo from "@src/components/BlogPostInfo.astro"; -import "@src/styles/blog/index.scss"; +import { getCollection } from "astro:content"; -let posts = await Astro.glob("../content/docs/blog/**/*.(mdx|md)"); -posts = posts.sort((a, b) => { - return new Date(b.frontmatter.pubDate).valueOf() - new Date(a.frontmatter.pubDate).valueOf(); -}); +const posts = (await getCollection("blog")).sort( + (a, b) => + new Date(b.data.pubDate).valueOf() - new Date(a.data.pubDate).valueOf() +); ---
- RSS + RSS -
- {posts.filter(post => post.frontmatter.url).map((post) => )} +
+ { + posts.map(async (post) => ( + + )) + }
diff --git a/website/src/content/authors/core.json b/website/src/content/authors/core.json new file mode 100644 index 000000000000..4d1cab6245b6 --- /dev/null +++ b/website/src/content/authors/core.json @@ -0,0 +1,4 @@ +{ + "name": "Biome Core Team", + "avatar": "/img/circle-indent-logo.svg" +} diff --git a/website/src/content/authors/ema.json b/website/src/content/authors/ema.json new file mode 100644 index 000000000000..2a35b52fb46a --- /dev/null +++ b/website/src/content/authors/ema.json @@ -0,0 +1,5 @@ +{ + "name": "Emanuele Stoppa", + "avatar": "https://avatars.githubusercontent.com/u/602478?v=4", + "url": "https://twitter.com/ematipico" +} diff --git a/website/src/content/authors/team.json b/website/src/content/authors/team.json new file mode 100644 index 000000000000..65e686e3955e --- /dev/null +++ b/website/src/content/authors/team.json @@ -0,0 +1,4 @@ +{ + "name": "Biome Core Team, Biome Maintainers", + "avatar": "/img/circle-indent-logo.svg" +} diff --git a/website/src/content/docs/blog/annoucing-biome.mdx b/website/src/content/blog/annoucing-biome.mdx similarity index 85% rename from website/src/content/docs/blog/annoucing-biome.mdx rename to website/src/content/blog/annoucing-biome.mdx index 0d0de4290aac..beee35ed75c2 100644 --- a/website/src/content/docs/blog/annoucing-biome.mdx +++ b/website/src/content/blog/annoucing-biome.mdx @@ -1,18 +1,14 @@ --- title: Announcing Biome -template: splash -url: /blog/annoucing-biome description: Biome continues Rome's legacy; in this blog post, we explain why the fork, with some context and history. summary: Biome continues Rome's legacy; in this blog post, we explain why the fork, with some context and history. -authorName: Emanuele Stoppa -authorAvatar: https://avatars.githubusercontent.com/u/602478?v=4 -authorUrl: https://twitter.com/ematipico -coauthorName: Biome Core Team -coauthorAvatar: /img/circle-indent-logo.svg +authors: + - ema + - core pubDate: 2023-08-29 -layout: ../../../layouts/Blog.astro -coverImage: blog/announcing-biome/biome-logo-slogan.png -coverImageAltText: The name of the project - "Biome", with the slogan underneath that says "Toolchain of the web" +coverImage: + src: blog/announcing-biome/biome-logo-slogan.png + alt: The name of the project - "Biome", with the slogan underneath that says "Toolchain of the web" socialImage: blog/announcing-biome/biome-logo-slogan.png --- @@ -23,12 +19,12 @@ Biome is the **official** fork of Rome and it will continue to be Rome's legacy. Biome is **led and maintained** by the same people that maintained Rome so far. **Follow us**: + - [Github organization](https://github.com/biomejs) - [Official repository](https://github.com/biomejs/biome) - [Official discord server](https://discord.gg/BypW39g6Yc) - [Official twitter account](https://twitter.com/biomejs) - ## Background I want to give you some background and context, which could help you to get why the core team created a new project with a new name. If you're not interested, feel free to jump to the [next section](#enters-biome) @@ -64,13 +60,18 @@ A few new [OSS contributors](#the-core-team) joined the cause and helped in cont In June, I [gave a talk](https://portal.gitnation.org/contents/rome-a-modern-toolchain) about Rome at JsNation 2023. -Emanuele Stoppa on the stage of JsNation +Emanuele Stoppa on the stage of JsNation So, the project is still alive, but maintaining it has become challenging: + - I don't have admin rights on Discord, so I can't delegate moderation rights to other people; - I don't have access to the hosting platform of the website; - I don't have access to any registry (npm, VSCode, etc.); -- the project is still under the MIT license of Rome Tools Inc., which makes attributions and contributions seem foggy from a legal point of view (where's the company? I don't know). +- the project is still under the MIT license of Rome Tools Inc., which makes attributions and contributions seem foggy from a legal point of view (where's the company? I don't know). Many attempts to reach out to the current owner were all void. There was only one thing I could do. **[We could do](#the-core-team).** @@ -79,6 +80,7 @@ Many attempts to reach out to the current owner were all void. There was only on We created Biome. After weeks of discussions among the members of the core team and conversations with some friends, we thought that a clean slate was the best course of action. We pondered the idea of keeping the "rome" name in the new fork, but that was proven difficult: + - Sebastian has registered tons of stuff with the "rome" name (GitHub organizations, website domains, open collectives, npm organizations). Finding the right combination wasn't easy; - without the proper rights in the Discord server, we couldn't delegate the moderation rights. Discord is a very important asset for community building; - keeping the name would have caused some attribution to Rome Tools Inc., making things still foggy when it comes to the legal aspects of the source code; @@ -89,8 +91,11 @@ Given all these difficulties, the core team settled for a new project. ### "New is always better." -
- +
+
Biome will embrace the same [philosophy](https://biomejs.dev/internals/philosophy) of the old Rome and the same mission. Although, the roadmap will likely change, and the core team could decide to focus on making the current features more stable instead of releasing new ones. @@ -99,13 +104,14 @@ Still, the primary mission is alive, and Biome wants to be a 360° toolchain; we ### Why Biome -The team wanted to create a second "Rome", a second version of it. So we fused the words "Bis" and "Rome". **Biome"". +The team wanted to create a second "Rome", a second version of it. So we fused the words "Bis" and "Rome". \*\*Biome"". ## I still use the `rome` package. What should I do? The `rome` package **_won't be maintained anymore_** by the core team, so you won't get any more releases. 1. You should use the `@biomejs/biome` package. Note that Biome also comes with a lot of new features and fixes. We've just prepared a [blog post](/blog/biome-v1) for that. + ```diff { - "rome": "12.1.3" @@ -114,41 +120,41 @@ The `rome` package **_won't be maintained anymore_** by the core team, so you wo ``` 2. And change the CLI name in your scripts: - ```diff + ```diff { - "scripts": { + "scripts": { - "format": "rome format --write ./src", + "format": "biome format --write ./src" - } + } } - ``` + ``` 3. In your `rome.json` file, update the URL of the `$schema` field: - ```diff - { - - "$schema": "https://docs.rome.tools/schemas/12.1.3/schema.json", - + "$schema": "https://biomejs.dev/schemas/1.0.0/schema.json" - } - ``` + ```diff + { + - "$schema": "https://docs.rome.tools/schemas/12.1.3/schema.json", + + "$schema": "https://biomejs.dev/schemas/1.0.0/schema.json" + } + ``` 4. Then install the new official [VSCode](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) or [open VSX](https://open-vsx.org/extension/biomejs/biome) extension. That's an important step if you use these extensions. 5. After the installation of the extension, open the `settings.json`. If you have some Rome related settings there, you'll have to update them: - ```diff - { - "[javascript]": { - - "editor.defaultFormatter": "rome.rome" - + "editor.defaultFormatter": "biomejs.biome" - }, - "editor.codeActionsOnSave": { - - "quickfix.rome": true, - - "source.organizeImports.rome": true - + "quickfix.biome": true, - + "source.organizeImports.biome": true - } - } - ``` + ```diff + { + "[javascript]": { + - "editor.defaultFormatter": "rome.rome" + + "editor.defaultFormatter": "biomejs.biome" + }, + "editor.codeActionsOnSave": { + - "quickfix.rome": true, + - "source.organizeImports.rome": true + + "quickfix.biome": true, + + "source.organizeImports.biome": true + } + } + ``` Biome **still accepts the `rome.json` file** as a configuration, so you don't need to do anything yet. Biome also takes `biome.json` as a configuration file. diff --git a/website/src/content/docs/blog/biome-v1.mdx b/website/src/content/blog/biome-v1.mdx similarity index 72% rename from website/src/content/docs/blog/biome-v1.mdx rename to website/src/content/blog/biome-v1.mdx index 667e66e8df65..42a09bbc5e0d 100644 --- a/website/src/content/docs/blog/biome-v1.mdx +++ b/website/src/content/blog/biome-v1.mdx @@ -1,16 +1,11 @@ --- title: Biome v1 -url: /blog/biome-v1 -template: splash description: New formatter options, CLI improvements, JSONC support and more. summary: New formatter options, CLI improvements, JSONC support and more. -authorName: Emanuele Stoppa -authorAvatar: https://avatars.githubusercontent.com/u/602478?v=4 -authorUrl: https://twitter.com/ematipico -coauthorName: Biome Core Team -coauthorAvatar: /img/circle-indent-logo.svg +authors: + - ema + - core pubDate: 2023-08-29 -layout: ../../../layouts/Blog.astro socialImage: social-logo.png --- @@ -29,10 +24,10 @@ Or install the [VS Code extension](https://marketplace.visualstudio.com/items?it ## New formatter options Biome now supports two new, long-awaited options: + - support for formatting the preferred quote kind in JSX; - support for formatting parenthesis in arrow functions only when they are needed; - ### JSX quotes style You can use this option via CLI or via `biome.json` file: @@ -40,9 +35,9 @@ You can use this option via CLI or via `biome.json` file: ```json title="biome.json" { "javascript": { - "formatter": { - "jsxQuoteStyle": "single" - } + "formatter": { + "jsxQuoteStyle": "single" + } } } ``` @@ -57,8 +52,8 @@ And Biome will apply single quotes when defining attributes in JSX code: import Item from "./item.jsx"; const Header = () => { - return ; -} + return ; +}; ``` ### Arrow function parenthesis @@ -68,9 +63,9 @@ You can decide not to print parenthesis in arrow functions. You can customize th ```json title="biome.json" { "javascript": { - "formatter": { - "arrowParentheses": "asNeeded" - } + "formatter": { + "arrowParentheses": "asNeeded" + } } } ``` @@ -83,9 +78,9 @@ And Biome will print parenthesis only for those arrow functions that require the ```jsx // no need for parentheses -const filter = term => {}; +const filter = (term) => {}; // needs parentheses -const filterBy = (term, fn) => {} +const filterBy = (term, fn) => {}; ``` ## CLI improvements @@ -95,8 +90,8 @@ The CLI was heavily reworked to guarantee consistent behaviour when handling fil Among those changes, there are some **breaking changes** in its behaviour. - The CLI exits with an error code if the configuration file contains errors; while Biome can parse the configuration successfully - even with errors - this was a hazard for our users. -A typo in the configuration file would have resulted in Biome applying its defaults, and executing Biome with a different behaviour compared to the one set by the user. -- The command `biome check` will now emit error diagnostics for *code not formatted* and exits with an error code. This behaviour aligns with the semantics meant for this command. + A typo in the configuration file would have resulted in Biome applying its defaults, and executing Biome with a different behaviour compared to the one set by the user. +- The command `biome check` will now emit error diagnostics for _code not formatted_ and exits with an error code. This behaviour aligns with the semantics meant for this command. ### New `biome lint` command @@ -115,7 +110,7 @@ You can define this behaviour in the `biome.json` too: ```json title="biome.json" { "files": { - "ignoreUnknown": true + "ignoreUnknown": true } } ``` @@ -135,12 +130,12 @@ Here's an example, let's change the diagnostic level of a rule via `biome.json`: ```json title="biome.json" { "linter": { - "recommended": true, - "rules": { - "a11y": { - "useAltText": "warn" + "recommended": true, + "rules": { + "a11y": { + "useAltText": "warn" + } } - } } } ``` @@ -149,8 +144,8 @@ Here's a sample code that will trigger the rule: ```jsx const Image = () => { - return -} + return ; +}; ``` And now, run the CLI using the new option: @@ -174,9 +169,9 @@ Biome can parse comments inside JSON files. You can opt-in to this feature via t ```json title="biome.json" { "json": { - "parser": { - "allowComments": true - } + "parser": { + "allowComments": true + } } } ``` @@ -211,35 +206,35 @@ We **deleted** two rules: - [`noDuplicateJsonKeys`](/linter/rules/no-duplicate-json-keys/) - This rule disallows duplicate keys in a JSON object. + This rule disallows duplicate keys in a JSON object. - [`noExcessiveComplexity`](/linter/rules/no-excessive-complexity/) - This rule computes a complexity score and reports code with a score above a configurable threshold. + This rule computes a complexity score and reports code with a score above a configurable threshold. - [`noFallthroughSwitchClause`](/linter/rules/no-fallthrough-switch-clause/) - This rule disallows `switch` cases that fall through to the next `case`. + This rule disallows `switch` cases that fall through to the next `case`. - [`noGlobalIsFinite`](/linter/rules/no-global-is-finite/) - This rule recommends using `Number.isFinite` instead of the global and unsafe `isFinite` that attempts a type of coercion. + This rule recommends using `Number.isFinite` instead of the global and unsafe `isFinite` that attempts a type of coercion. - [`noGlobalIsNan`](/linter/rules/no-global-is-nan/) - This rule recommends using `Number.isNaN` instead of the global and unsafe `isNaN` that attempts a type of coercion. + This rule recommends using `Number.isNaN` instead of the global and unsafe `isNaN` that attempts a type of coercion. - [`noNonoctalDecimalEscape`](/linter/rules/no-nonoctal-decimal-escape/) - This rule disallows `\8` and `\9` escape sequences in string literals. + This rule disallows `\8` and `\9` escape sequences in string literals. - [`noUnsafeDeclarationMerging`](/linter/rules/no-unsafe-declaration-merging/) - This rule disallows declaration merging between an interface and a class. + This rule disallows declaration merging between an interface and a class. - [`noUselessEmptyExport`](/linter/rules/no-useless-empty-export/) - This rule disallows useless `export {}`. + This rule disallows useless `export {}`. - [noUselessThisAlias](/linter/rules/no-useless-this-alias/) @@ -247,12 +242,12 @@ We **deleted** two rules: - [`noVoid`](/linter/rules/no-void/) - This rule disallows the use of `void`. + This rule disallows the use of `void`. - [`useArrowFunction`](/linter/rules/use-arrow-function/) - This rule proposes turning function expressions into arrow functions. - Function expressions that use `this` are ignored. + This rule proposes turning function expressions into arrow functions. + Function expressions that use `this` are ignored. - [`useGetterReturn`](/linter/rules/use-getter-return/) @@ -260,15 +255,15 @@ We **deleted** two rules: - [`useImportRestrictions`](/linter/rules/use-import-restrictions/) - Enables restrictions on how local imports should be imported. + Enables restrictions on how local imports should be imported. - [`useIsArray`](/linter/rules/use-is-array/) - This rule proposes using `Array.isArray()` instead of `instanceof Array`. + This rule proposes using `Array.isArray()` instead of `instanceof Array`. - [`useNamingConvention`](/linter/rules/use-naming-convention/) - The rule enforces wide-spread naming conventions of Javascript and TypeScript across a codebase. + The rule enforces wide-spread naming conventions of Javascript and TypeScript across a codebase. #### Promoted rules @@ -304,9 +299,9 @@ Some users were dissatisfied because they couldn't use Biome inside their Angula ```json title="biome.json" { "javascript": { - "parser": { - "unsafeParameterDecoratorsEnabled": true - } + "parser": { + "unsafeParameterDecoratorsEnabled": true + } } } ``` @@ -324,77 +319,45 @@ Big thank you to the following contributors: - [ddanielsantos](https://github.com/ddanielsantos), for their first contribution to the project; - [nikeee](https://github.com/nikeee), for their first contribution to the project; -[//]: # (KEEP IT, NEEDED FOR THE FUTURE) -[//]: # () -[//]: # () -[//]: # (
) - -[//]: # (
) - -[//]: # (

Enable all rules

) - -[//]: # () -[//]: # ( Biome will enable all rules, even the ones that belong to `nursery` group:) - -[//]: # ( ```json title="biome.json") - -[//]: # ( {) - -[//]: # ( "linter": {) - -[//]: # ( "enabled": true,) - -[//]: # ( "rule": {) - -[//]: # ( "all": true) - -[//]: # ( }) - -[//]: # ( }) - -[//]: # ( }) - -[//]: # ( ```) - -[//]: # () -[//]: # (
) - -[//]: # () -[//]: # (
) - -[//]: # (

Only some rules

) - -[//]: # () -[//]: # ( Biome will disable **all** rules and enable only the rules that belong to `correctness` group:) - -[//]: # ( ```json title="biome.json") - -[//]: # ( {) - -[//]: # ( "linter": {) - -[//]: # ( "enabled": true,) - -[//]: # ( "rule": {) - -[//]: # ( "all": false,) - -[//]: # ( "correctness": {) - -[//]: # ( "all": true) - -[//]: # ( }) - -[//]: # ( }) - -[//]: # ( }) - -[//]: # ( }) - -[//]: # ( ```) - -[//]: # () -[//]: # (
) - -[//]: # () -[//]: # (
) +[//]: # "KEEP IT, NEEDED FOR THE FUTURE" +[//]: # +[//]: # +[//]: # '
' +[//]: # '
' +[//]: # "

Enable all rules

" +[//]: # +[//]: # " Biome will enable all rules, even the ones that belong to `nursery` group:" +[//]: # ' ```json title="biome.json"' +[//]: # " {" +[//]: # ' "linter": {' +[//]: # ' "enabled": true,' +[//]: # ' "rule": {' +[//]: # ' "all": true' +[//]: # " }" +[//]: # " }" +[//]: # " }" +[//]: # " ```" +[//]: # +[//]: # "
" +[//]: # +[//]: # '
' +[//]: # "

Only some rules

" +[//]: # +[//]: # " Biome will disable **all** rules and enable only the rules that belong to `correctness` group:" +[//]: # ' ```json title="biome.json"' +[//]: # " {" +[//]: # ' "linter": {' +[//]: # ' "enabled": true,' +[//]: # ' "rule": {' +[//]: # ' "all": false,' +[//]: # ' "correctness": {' +[//]: # ' "all": true' +[//]: # " }" +[//]: # " }" +[//]: # " }" +[//]: # " }" +[//]: # " ```" +[//]: # +[//]: # "
" +[//]: # +[//]: # "
" diff --git a/website/src/content/docs/blog/biome-wins-prettier-challenge.md b/website/src/content/blog/biome-wins-prettier-challenge.md similarity index 98% rename from website/src/content/docs/blog/biome-wins-prettier-challenge.md rename to website/src/content/blog/biome-wins-prettier-challenge.md index 4477efec45b7..cc753dc62179 100644 --- a/website/src/content/docs/blog/biome-wins-prettier-challenge.md +++ b/website/src/content/blog/biome-wins-prettier-challenge.md @@ -1,18 +1,14 @@ --- title: Biome formatter wins the Prettier challenge -template: splash -url: /blog/biome-wins-prettier-challenge description: Biome formatter now 95% compatible with Prettier summary: Biome formatter now 95% compatible with Prettier -authorName: Emanuele Stoppa -authorAvatar: https://avatars.githubusercontent.com/u/602478?v=4 -authorUrl: https://twitter.com/ematipico -coauthorName: Biome Core Team, Biome Maintainers -coauthorAvatar: /img/circle-indent-logo.svg +authors: + - ema + - team pubDate: 2023-11-27 -layout: ../../../layouts/Blog.astro -coverImage: blog/prettier-challenge.png -coverImageAltText: The Prettier challenge banner, with the Biome logo over it +coverImage: + src: blog/prettier-challenge.png + alt: The Prettier challenge banner, with the Biome logo over it socialImage: blog/prettier-challenge.png --- @@ -28,7 +24,7 @@ pnpm update --save-exact @biomejs/biome@1.4.0 yarn upgrade --exact @biomejs/biome@1.4.0 ``` -## Better formatter +## Better formatter Biome formatter has now **over 96% in terms of compatibility** against [Prettier](https://prettier.io/)! This score is computed for JavaScript, TypeScript, and JSX formatting. @@ -37,6 +33,7 @@ Merit of challenge that was launched by [Christopher Chedeau](https://twitter.co The challenge attracted the attention of many people, and some of them decided to contribute to Biome to claim part of the bounty. I did see something amazing: contributors had an amazing coordination, they took ownership of the tasks and delivered the solution in a matter of hours. I believe the main factors that made this possible are three: + 1. Money. It's a fact, and it's completely fine if someone decides to contribute only for earning a small stipend out of it. 2. Communication. We used [GitHub](https://github.com/biomejs/biome/issues/720) as only medium of coordination. We provided information, instructions and help on how to deliver. 3. Infrastructure. Biome relies on a solid testing infrastructure, built by [previous](https://github.com/MichaReiser) Rome Tools [employees](https://github.com/ematipico) and [contributors](https://github.com/IWANABETHATGUY/). It's able to catch every reformat bug, provide granular diffs and warn the user if the emitted output is the different from the one emitted by Prettier. @@ -57,6 +54,7 @@ If there's a divergence that isn't documented in our website, you should conside #### New formatting options With this challenge, we added new options to the formatter: + - [`lineEnding`](/reference/configuration#formatterlineending) Use this option to match the line endings of your OS. We support `lf` (line feed - `\n`), `cr` (carriage return - `\r`) and `crlf` (carriage return line feed - `\r\n`). @@ -101,14 +99,14 @@ With this challenge, we added new options to the formatter: ```js title="example.js" import { sort } from "sort.js"; - const value = { sort } + const value = { sort }; ``` After formatting with `"bracketSpacing": false`: ```js title="example.js" - import {sort} from "sort.js"; - const value = {sort} + import { sort } from "sort.js"; + const value = { sort }; ``` ## VSCode extension goodies @@ -130,7 +128,7 @@ People that rely on Biome LSP will be pleased that they can now pass a custom co ```shell biome --config-path=../path/where/config/is lsp-proxy biome --config-path=../path/where/config/is start -```` +``` The CLI now exposes the option `--diagnostic-level`, that allows to filter the kind of diagnostics printed to terminal. @@ -145,22 +143,23 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru ### New rules - [noDefaultExport](https://biomejs.dev/linter/rules/no-default-export) + ```jsx - export default function f() {}; + export default function f() {} ```
nursery/noDefaultExport.js:1:8 lint/nursery/noDefaultExport ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
+  
      Avoid default exports.
-
+  
     > 1 │ export default function f() {};
             ^^^^^^^
       2 │ 
-
+  
      Default exports cannot be easily discovered inside an editor and don't encourage the use of consistent names through a code base.
-
+  
      Use a named export instead.
-
+  
   
- [noAriaHiddenOnFocusable](https://biomejs.dev/linter/rules/no-aria-hidden-on-focusable) @@ -170,17 +169,17 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru ```
nursery/noAriaHiddenOnFocusable.js:1:1 lint/nursery/noAriaHiddenOnFocusable  FIXABLE  ━━━━━━━━━━━━━━
-
+  
      Disallow aria-hidden="true" from being set on focusable elements.
-
+  
     > 1 │ <div aria-hidden="true" tabIndex="0" />
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       2 │ 
-
+  
      aria-hidden should not be set to true on focusable elements because this can lead to confusing behavior for screen reader users.
-
+  
      Unsafe fix: Remove the aria-hidden attribute from the element.
-
+  
       1 │ <div·aria-hidden="true"·tabIndex="0"·/>
          -------------------
   
@@ -193,31 +192,31 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru ```
nursery/noImplicitAnyLet.js:1:5 lint/nursery/noImplicitAnyLet ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
+  
      This variable has implicitly the any type.
-
+  
     > 1 │ var a;
          ^
       2 │ a = 2;
       3 │ 
-
+  
      Variable declarations without type annotation and initialization have implicitly the any type. Declare type or initialize the variable with some value.
-
+  
   
- [useAwait](https://biomejs.dev/linter/rules/use-await) ```jsx async function fetchData() { - // Missing `await` for the promise returned by `fetch` - return fetch('/data'); + // Missing `await` for the promise returned by `fetch` + return fetch("/data"); } ```
nursery/useAwait.js:1:1 lint/nursery/useAwait ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
+  
      This async function lacks an await expression.
-
+  
     > 1 │ async function fetchData() {
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     > 2 │ // Missing `await` for the promise returned by `fetch`
@@ -225,9 +224,9 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru
     > 4 │ }
      ^
       5 │ 
-
+  
      Remove this async modifier, or add an await expression in the function.
-
+  
     > 1 │ async function fetchData() {
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     > 2 │ // Missing `await` for the promise returned by `fetch`
@@ -235,10 +234,11 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru
     > 4 │ }
      ^
       5 │ 
-
+  
      Async functions without await expressions may not need to be declared async.
-
+  
   
+ - [useValidAriaRole](https://biomejs.dev/linter/rules/use-valid-aria-role) ```jsx @@ -246,18 +246,18 @@ Biome is a linter too, and it features [177 rules](https://biomejs.dev/linter/ru ```
nursery/useValidAriaRole.js:1:1 lint/nursery/useValidAriaRole  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
+  
      Enforce that elements with ARIA roles must use a valid, non-abstract ARIA role.
-
+  
     > 1 │ <div role="datepicker"></div>
      ^^^^^^^^^^^^^^^^^^^^^^^
       2 │ 
-
+  
      Check WAI-ARIA for valid roles or provide options accordingly.
-
+  
      Unsafe fix: Remove the invalid role attribute.
        Check the list of all valid role attributes.
-
+  
       1 │ <div·role="datepicker"></div>
          -----------------
   
@@ -293,23 +293,23 @@ new RegExp("abc", "u"); ```jsx ``` -
a11y/noAccessKey.js:1:22 lint/a11y/noAccessKey  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
+  
a11y/noAccessKey.js:1:22 lint/a11y/noAccessKey  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+  
      Avoid the accessKey attribute to reduce inconsistencies between keyboard shortcuts and screen reader keyboard comments.
-
+  
     > 1 │ <input type="submit" accessKey="s" value="Submit" />
                           ^^^^^^^^^^^^^
       2 │ 
-
+  
      Assigning keyboard shortcuts using the accessKey attribute leads to inconsistent keyboard actions across applications.
-
+  
      Unsafe fix: Remove the accessKey attribute.
-
+  
       1 │ <input·type="submit"·accessKey="s"·value="Submit"·/>
                          --------------
   
- - [a11y/useHeadingContent](https://biomejs.dev/linter/rules/use-heading-content) ```jsx @@ -317,15 +317,15 @@ new RegExp("abc", "u"); ```
a11y/useHeadingContent.js:1:1 lint/a11y/useHeadingContent ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
+  
      Provide screen reader accessible content when using heading  elements.
-
+  
     > 1 │ <h1 />
      ^^^^^^
       2 │ 
-
+  
      All headings on a page should have content that is accessible to screen readers.
-
+  
   
- [complexity/useSimpleNumberKeys](https://biomejs.dev/linter/use-simple-number-keys) @@ -335,22 +335,21 @@ new RegExp("abc", "u"); ```
complexity/useSimpleNumberKeys.js:1:4 lint/complexity/useSimpleNumberKeys  FIXABLE  ━━━━━━━━━━━━━━━━
-
+  
      Hexadecimal number literal is not allowed here.
-
+  
     > 1 │ ({ 0x1: 1 });
         ^^^
       2 │ 
-
+  
      Safe fix: Replace 0x1 with 1
-
+  
   1  - ({·0x1:·1·});
     1+ ({·1:·1·});
   2 2
-
+  
   
- ### Promoted rules - [a11y/noInteractiveElementToNoninteractiveRole](https://biomejs.dev/linter/rules/no-interactive-element-to-noninteractive-role) @@ -371,17 +370,18 @@ new RegExp("abc", "u"); The rule is replaced by [correctness/noInvalidNewBuiltin](https://biomejs.dev/linter/rules/no-invalid-new-builtin) - ## Homage to our maintainers Since Biome was forked, new people joined the project. They have been helping with in so many ways that you can't even imagine: new features, side projects, engaging with the community, support, documentation, and more. OSS is not just about coding. Thank you to: + - [Madeline Gurriarán @SuperchupuDev](https://github.com/SuperchupuDev) - [Nicolas Hedger @nhedger](https://github.com/nhedger) - [Victor Teles @victor-teles](https://github.com/victor-teles) And a big welcome to our new joined maintainer: + - [Jon Egeland @faultyserver](https://github.com/faultyserver) - [Takayuki Maeda @TaKO8Ki](https://github.com/TaKO8Ki) diff --git a/website/src/content/config.ts b/website/src/content/config.ts index eef2bd8560a8..90e2a7cb1381 100644 --- a/website/src/content/config.ts +++ b/website/src/content/config.ts @@ -1,7 +1,41 @@ import { docsSchema } from "@astrojs/starlight/schema"; // src/content/config.ts -import { defineCollection } from "astro:content"; +import { defineCollection, z } from "astro:content"; + +const blogSchema = z.object({ + title: z.string(), + subtitle: z.string().optional(), + pubDate: z + .string() + .or(z.date()) + .transform((val) => new Date(val)), + summary: z.string(), + description: z.string(), + authors: z.array(z.string()), + coverImage: z + .object({ + src: z.string(), + caption: z.string().optional(), + alt: z.string(), + }) + .optional(), + socialImage: z.string(), +}); + +const authorsSchema = z.object({ + name: z.string(), + avatar: z.string(), + url: z.string().optional(), +}); export const collections = { docs: defineCollection({ schema: docsSchema() }), + blog: defineCollection({ + type: "content", + schema: blogSchema, + }), + authors: defineCollection({ + type: "data", + schema: authorsSchema, + }), }; diff --git a/website/src/content/docs/blog/index.mdx b/website/src/content/docs/blog/index.mdx deleted file mode 100644 index a7e803feb127..000000000000 --- a/website/src/content/docs/blog/index.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Blog -prev: false -next: false -template: splash ---- -import "@src/styles/blog/index.scss"; -import PostsList from "@src/components/PostsList.astro"; - - diff --git a/website/src/layouts/Blog.astro b/website/src/layouts/Blog.astro index 073d458ab719..fb6c5ab8f447 100644 --- a/website/src/layouts/Blog.astro +++ b/website/src/layouts/Blog.astro @@ -1,27 +1,31 @@ --- +import type { CollectionEntry } from "astro:content"; +import BlogPostInfo from "@src/components/BlogPostInfo.astro"; + export interface Props { - coverImage?: string; - coverImageCaption?: string; - coverImageAltText?: string; - subtitle: string; - title: string; + post: CollectionEntry<"blog">["data"]; } -import BlogPostInfo from "../components/BlogPostInfo.astro"; - -const {coverImage, coverImageCaption, coverImageAltText, subtitle, title} = Astro.props.frontmatter; +const { post } = Astro.props; --- - {coverImage &&
- {coverImageAltText} - {coverImageCaption &&
{coverImageCaption}
} -
} + { + post.coverImage && ( +
+ {post.coverImage.alt} + {post.coverImage.caption && ( +
+ {post.coverImage.caption} +
+ )} +
+ ) + } - {subtitle &&
{subtitle}
} + {post.subtitle &&
{post.subtitle}
} - + - +
- diff --git a/website/src/layouts/StarlightSplashLayout.astro b/website/src/layouts/StarlightSplashLayout.astro new file mode 100644 index 000000000000..661f92859539 --- /dev/null +++ b/website/src/layouts/StarlightSplashLayout.astro @@ -0,0 +1,76 @@ +--- +// @ts-expect-error +import type { LocaleData } from "@astrojs/starlight/utils/slugs"; +import Page from "@astrojs/starlight/components/Page.astro"; + +export interface Props { + title: string; + slug: string; + editUrl?: string; +} + +function getPageProps(title: string, slug: string, editUrl?: string) { + const entryMeta = { dir: "ltr", lang: "en", locale: undefined } as LocaleData; + + return { + ...entryMeta, + editUrl: editUrl ? new URL(editUrl) : undefined, + entry: { + data: { + head: [ + { + tag: "title", + content: `${title} | Biome`, + }, + ], + pagefind: false, + title, + template: "splash", + }, + slug, + }, + entryMeta, + hasSidebar: false, + headings: [], + id: slug, + lastUpdated: undefined, + pagination: { + next: undefined, + prev: undefined, + }, + sidebar: [], + slug, + toc: { + items: [], + maxHeadingLevel: 0, + minHeadingLevel: 0, + }, + }; +} + +const { title, slug, editUrl } = Astro.props; + +const pageProps = getPageProps(title, slug, editUrl); +--- + + + + + + diff --git a/website/src/pages/blog/[...slug].astro b/website/src/pages/blog/[...slug].astro new file mode 100644 index 000000000000..13e703b40435 --- /dev/null +++ b/website/src/pages/blog/[...slug].astro @@ -0,0 +1,32 @@ +--- +import { getCollection, type CollectionEntry } from "astro:content"; +import BlogLayout from "@src/layouts/Blog.astro"; +import StarlightSplashLayout from "@src/layouts/StarlightSplashLayout.astro"; + +export async function getStaticPaths() { + const blogEntries = await getCollection("blog"); + return blogEntries.map((entry) => ({ + params: { slug: entry.slug }, + props: { entry }, + })); +} + +interface Props { + entry: CollectionEntry<"blog">; +} + +const { entry } = Astro.props; +const { Content } = await entry.render(); + +const post = entry.data; +--- + + + + + + diff --git a/website/src/pages/blog/index.astro b/website/src/pages/blog/index.astro new file mode 100644 index 000000000000..e39366462c94 --- /dev/null +++ b/website/src/pages/blog/index.astro @@ -0,0 +1,8 @@ +--- +import PostsList from "@src/components/PostsList.astro"; +import StarlightSplashLayout from "@src/layouts/StarlightSplashLayout.astro"; +--- + + + + diff --git a/website/src/pages/feed.xml.js b/website/src/pages/feed.xml.js index e58ba98f6da7..3a0c203fdbdc 100644 --- a/website/src/pages/feed.xml.js +++ b/website/src/pages/feed.xml.js @@ -1,11 +1,22 @@ -import rss, { pagesGlobToRssItems } from "@astrojs/rss"; +import rss from "@astrojs/rss"; +import { getCollection } from "astro:content"; + +export async function get(context) { + const posts = (await getCollection("blog")).sort( + (a, b) => + new Date(b.data.pubDate).valueOf() - new Date(a.data.pubDate).valueOf(), + ); -export async function get() { return rss({ title: "Biome Blog", - description: "", - site: import.meta.env.SITE, - items: await pagesGlobToRssItems(import.meta.glob("./blog/**/*.mdx")), + description: "Biome's toolchain official blog", + site: context.site, + items: posts.map((post) => ({ + title: post.data.title, + pubDate: post.data.pubDate, + description: post.data.description, + link: `/blog/${post.slug}`, + })), customData: "en-us", }); }