From 36e5c8fa2f3a480a8fbb309ebd86bb1fd897ea24 Mon Sep 17 00:00:00 2001 From: ksen0 Date: Sun, 13 Apr 2025 12:56:20 +0200 Subject: [PATCH] Merge attribution and contributor docs form main to 2.0 --- .all-contributorsrc | 401 +++++- README.md | 81 +- contributor_docs/README.md | 2 +- contributor_docs/archive/es6-adoption.md | 2 +- .../contributing_to_the_p5js_reference.md | 4 +- contributor_docs/contributor_guidelines.md | 4 +- contributor_docs/creating_libraries.md | 4 +- contributor_docs/documentation_style_guide.md | 6 +- contributor_docs/friendly_error_system.md | 2 +- .../how-to-add-friendly-error-messages.md | 2 +- contributor_docs/method.example.js | 6 +- .../project_wrapups/orenshoham_gsoc_2019.md | 6 +- .../project_wrapups/sanket_gsoc_2019.md | 2 +- .../project_wrapups/wong_gsoc_2023.md | 6 +- contributor_docs/release_process.md | 2 +- contributor_docs/steward_guidelines.md | 8 +- contributor_docs/unit_testing.md | 6 +- .../zh-Hans/documentation_style_guide.md | 1246 +++++++++++++++++ .../zh-Hans/fes_contribution_guide.md | 526 +++++++ .../how-to-add-friendly-error-messages.md | 316 +++++ 20 files changed, 2559 insertions(+), 73 deletions(-) create mode 100644 contributor_docs/zh-Hans/documentation_style_guide.md create mode 100644 contributor_docs/zh-Hans/fes_contribution_guide.md create mode 100644 contributor_docs/zh-Hans/how-to-add-friendly-error-messages.md diff --git a/.all-contributorsrc b/.all-contributorsrc index 55809f85bd..adb21ac26b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1326,7 +1326,8 @@ "profile": "https://aatishb.com", "contributions": [ "doc", - "bug" + "bug", + "example" ] }, { @@ -1391,7 +1392,8 @@ "contributions": [ "bug", "code", - "doc" + "doc", + "example" ] }, { @@ -1400,7 +1402,8 @@ "avatar_url": "https://avatars2.githubusercontent.com/u/9020979?s=460&v=4", "profile": "https://github.com/hydrosquall", "contributions": [ - "doc" + "doc", + "example" ] }, { @@ -1797,16 +1800,6 @@ "example" ] }, - { - "login": "mjaything", - "name": "Minjun Kim", - "avatar_url": "https://avatars1.githubusercontent.com/u/13192500?v=4", - "profile": "https://github.com/mjaything", - "contributions": [ - "bug", - "translation" - ] - }, { "login": "fisherdiede", "name": "Fisher Diede", @@ -1851,7 +1844,8 @@ "avatar_url": "https://avatars1.githubusercontent.com/u/36653440?v=4", "profile": "https://github.com/sm7515", "contributions": [ - "doc" + "doc", + "example" ] }, { @@ -2174,7 +2168,8 @@ "avatar_url": "https://avatars1.githubusercontent.com/u/56646605?v=4", "profile": "https://berkeozgen.me/", "contributions": [ - "bug" + "bug", + "example" ] }, { @@ -2495,7 +2490,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/43292181?v=4", "profile": "https://github.com/suhascv", "contributions": [ - "doc" + "doc", + "example" ] }, { @@ -2555,7 +2551,8 @@ "profile": "http://www.davepagurek.com", "contributions": [ "code", - "test" + "test", + "example" ] }, { @@ -3323,7 +3320,8 @@ "profile": "https://github.com/Malayvasa", "contributions": [ "design", - "code" + "code", + "example" ] }, { @@ -3659,7 +3657,8 @@ "contributions": [ "ideas", "review", - "plugin" + "plugin", + "example" ] }, { @@ -3767,7 +3766,8 @@ "profile": "http://aceslowman.com", "contributions": [ "code", - "doc" + "doc", + "example" ] }, { @@ -3947,7 +3947,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/74553433?v=4", "profile": "https://github.com/Acha0203", "contributions": [ - "code" + "code", + "example" ] }, { @@ -4091,7 +4092,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/92529?v=4", "profile": "http://jareddonovan.com/", "contributions": [ - "code" + "code", + "example" ] }, { @@ -4460,7 +4462,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/22816171?v=4", "profile": "https://github.com/ihsavru", "contributions": [ - "code" + "code", + "example" ] }, { @@ -4523,7 +4526,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/19987520?v=4", "profile": "https://jithinks.netlify.app/", "contributions": [ - "code" + "code", + "example" ] }, { @@ -5330,7 +5334,16 @@ "avatar_url": "https://avatars.githubusercontent.com/u/127239756?v=4", "profile": "https://github.com/perminder-17", "contributions": [ - "code" + "code", + "bug", + "doc", + "example", + "ideas", + "plugin", + "projectManagement", + "promotion", + "question", + "research" ] }, { @@ -6210,7 +6223,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/7389189?v=4", "profile": "https://github.com/AaratiAkkapeddi", "contributions": [ - "code" + "code", + "ideas" ] }, { @@ -6445,6 +6459,341 @@ "code", "doc" ] + }, + { + "login": "philyawj", + "name": "Jordan Philyaw", + "avatar_url": "https://avatars.githubusercontent.com/u/37485853?v=4", + "profile": "http://jordanphilyaw.com", + "contributions": [ + "doc" + ] + }, + { + "login": "thrly", + "name": "oliver thurley", + "avatar_url": "https://avatars.githubusercontent.com/u/22343302?v=4", + "profile": "http://oliverthurley.co.uk", + "contributions": [ + "doc", + "code" + ] + }, + { + "login": "lirenjie95", + "name": "Renjie Li", + "avatar_url": "https://avatars.githubusercontent.com/u/17038472?v=4", + "profile": "https://github.com/lirenjie95", + "contributions": [ + "doc", + "code" + ] + }, + { + "login": "Vaivaswat2244", + "name": "Vaivaswat Dubey", + "avatar_url": "https://avatars.githubusercontent.com/u/113991324?v=4", + "profile": "https://github.com/Vaivaswat2244", + "contributions": [ + "code" + ] + }, + { + "login": "xinemata", + "name": "Xin Xin", + "avatar_url": "https://avatars.githubusercontent.com/u/9159424?v=4", + "profile": "https://github.com/xinemata", + "contributions": [ + "eventOrganizing", + "tutorial", + "talk", + "mentoring", + "ideas" + ] + }, + { + "login": "akkarn1689", + "name": "Ashish Karn", + "avatar_url": "https://avatars.githubusercontent.com/u/82334486?v=4", + "profile": "https://karn-ashish-16.onrender.com/", + "contributions": [ + "code" + ] + }, + { + "login": "dkessner", + "name": "Darren Kessner", + "avatar_url": "https://avatars.githubusercontent.com/u/1002034?v=4", + "profile": "https://dkessner.github.io/", + "contributions": [ + "example" + ] + }, + { + "login": "AnimeshSinha1309", + "name": "Animesh Sinha", + "avatar_url": "https://avatars.githubusercontent.com/u/9739218?v=4", + "profile": "http://www.facebook.com/AnimeshSinha1309", + "contributions": [ + "example" + ] + }, + { + "login": "katlich112358", + "name": "Kathryn Lichlyter", + "avatar_url": "https://avatars.githubusercontent.com/u/59926191?v=4", + "profile": "https://github.com/katlich112358", + "contributions": [ + "example" + ] + }, + { + "login": "geealbers", + "name": "Greg Albers", + "avatar_url": "https://avatars.githubusercontent.com/u/7796401?v=4", + "profile": "https://geealbers.net/", + "contributions": [ + "example" + ] + }, + { + "login": "macarena", + "name": "Marco Macarena", + "avatar_url": "https://avatars.githubusercontent.com/u/79822?v=4", + "profile": "http://macarena.pro.br", + "contributions": [ + "example" + ] + }, + { + "login": "khamiltonuk", + "name": "Kristian Hamilton", + "avatar_url": "https://avatars.githubusercontent.com/u/4013283?v=4", + "profile": "http://www.khamilton.co.uk", + "contributions": [ + "example" + ] + }, + { + "login": "keshavg2", + "name": "Keshav Gupta", + "avatar_url": "https://avatars.githubusercontent.com/u/34001173?v=4", + "profile": "https://keshav-portfolio-resume.netlify.app/", + "contributions": [ + "example" + ] + }, + { + "login": "riteshsp2000", + "name": "Ritesh Patil", + "avatar_url": "https://avatars.githubusercontent.com/u/56112399?v=4", + "profile": "http://riteshpatil.com", + "contributions": [ + "example" + ] + }, + { + "login": "gabrielsroka", + "name": "Gabriel Sroka", + "avatar_url": "https://avatars.githubusercontent.com/u/14354736?v=4", + "profile": "https://gabrielsroka.github.io", + "contributions": [ + "example" + ] + }, + { + "login": "kcconch", + "name": "Casey Conchinha", + "avatar_url": "https://avatars.githubusercontent.com/u/26172283?v=4", + "profile": "http://kccon.ch", + "contributions": [ + "example" + ] + }, + { + "login": "davidblitz", + "name": "davidblitz", + "avatar_url": "https://avatars.githubusercontent.com/u/13055497?v=4", + "profile": "https://github.com/davidblitz", + "contributions": [ + "example" + ] + }, + { + "login": "crh82", + "name": "crh82", + "avatar_url": "https://avatars.githubusercontent.com/u/103348212?v=4", + "profile": "https://github.com/crh82", + "contributions": [ + "example" + ] + }, + { + "login": "", + "name": "Aaron Welles", + "avatar_url": "https://hello-assets.p5js.org/placeholder_avatar.png", + "profile": "", + "contributions": [ + "example" + ] + }, + { + "login": "seyko1", + "name": "Seyko", + "avatar_url": "https://avatars.githubusercontent.com/u/26870879?v=4", + "profile": "https://github.com/seyko1", + "contributions": [ + "code" + ] + }, + { + "login": "thekinardist", + "name": "Xevi H. Aqeel", + "avatar_url": "https://avatars.githubusercontent.com/u/21345916?v=4", + "profile": "http://kinardist.media", + "contributions": [ + "example", + "design" + ] + }, + { + "login": "GregStanton", + "name": "Greg Stanton", + "avatar_url": "https://avatars.githubusercontent.com/u/51820777?v=4", + "profile": "https://www.youtube.com/c/HigherMathNotes", + "contributions": [ + "bug", + "code", + "doc", + "example", + "ideas", + "plugin", + "projectManagement", + "promotion", + "question", + "research" + ] + }, + { + "login": "bojidar-bg", + "name": "Bojidar Marinov", + "avatar_url": "https://avatars.githubusercontent.com/u/5276727?v=4", + "profile": "https://bojidar-bg.dev/", + "contributions": [ + "code", + "test" + ] + }, + { + "login": "ChloeYanYan", + "name": "Chloe Yan", + "avatar_url": "https://avatars.githubusercontent.com/u/181019103?v=4", + "profile": "https://github.com/ChloeYanYan", + "contributions": [ + "doc" + ] + }, + { + "login": "webermayank", + "name": "Mayank Verma", + "avatar_url": "https://avatars.githubusercontent.com/u/111176033?v=4", + "profile": "https://github.com/webermayank", + "contributions": [ + "code" + ] + }, + { + "login": "lab-mediaArts", + "name": "Lauren Berrios", + "avatar_url": "https://avatars.githubusercontent.com/u/179049131?v=4", + "profile": "https://github.com/lab-mediaArts", + "contributions": [ + "ideas" + ] + }, + { + "login": "roxi09", + "name": "roxi09", + "avatar_url": "https://avatars.githubusercontent.com/u/175943104?v=4", + "profile": "https://github.com/Roxi09", + "contributions": [ + "ideas" + ] + }, + { + "login": "jlliu", + "name": "Jackie Liu", + "avatar_url": "https://avatars.githubusercontent.com/u/8304517?v=4", + "profile": "https://github.com/jlliu", + "contributions": [ + "ideas" + ] + }, + { + "login": "re7l", + "name": "Carrie Wang", + "avatar_url": "https://avatars.githubusercontent.com/u/19353655?v=4", + "profile": "https://github.com/re7l", + "contributions": [ + "ideas" + ] + }, + { + "login": "himanshuukholiya", + "name": "Himanshu Kholiya", + "avatar_url": "https://avatars.githubusercontent.com/u/128818464?v=4", + "profile": "https://github.com/himanshuukholiya", + "contributions": [ + "code" + ] + }, + { + "login": "mclark414", + "name": "mclark414", + "avatar_url": "https://avatars.githubusercontent.com/u/26391144?v=4", + "profile": "https://github.com/mclark414", + "contributions": [ + "ideas" + ] + }, + { + "login": "mxramsey", + "name": "Mx. Ramsey", + "avatar_url": "https://avatars.githubusercontent.com/u/161327383?v=4", + "profile": "https://github.com/mxramsey", + "contributions": [ + "ideas" + ] + }, + { + "login": "franolichdesign", + "name": "Franolich Design", + "avatar_url": "https://avatars.githubusercontent.com/u/74784668?v=4", + "profile": "https://github.com/franolichdesign", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "HritvikBhatia", + "name": "Vik", + "avatar_url": "https://avatars.githubusercontent.com/u/149999573?v=4", + "profile": "https://github.com/HritvikBhatia", + "contributions": [ + "code", + "bug", + "translation" + ] + }, + { + "login": "Darrenhqf", + "name": "Qingfeng Huang", + "avatar_url": "https://avatars.githubusercontent.com/u/92257843?v=4", + "profile": "https://git.arts.ac.uk/pages/21034426/My_Portfolio_Website/", + "contributions": [ + "translation" + ] } ], "repoType": "github", diff --git a/README.md b/README.md index 19505fbabc..992deea94a 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,8 @@ Current Lead/Mentor * [@limzykenneth](https://github.com/limzykenneth) - p5.js Mentor,2023-present Lead/Mentor Alumni -* [@lmccart](https://github.com/lmccart)- p5.js Creator -* [@qianqianye](https://github.com/qianqianye) - p5.js Lead,2021-2024 +* [@lmccart](https://github.com/lmccart) - p5.js Creator +* [@qianqianye](https://github.com/qianqianye) - p5.js Lead,2021-present (on leave) * [@outofambit](https://github.com/outofambit) - p5.js Co-Lead 2021-22, Mentor 2022-2023 * [@mcturner1995](https://github.com/mcturner1995) - p5.js Lead 2020 @@ -353,7 +353,7 @@ We recognize all types of contributions. This project follows the [all-contribut Caroline Hermans
Caroline Hermans

💡 📖 Faith Wuyue Yu
Faith Wuyue Yu

- Aatish Bhatia
Aatish Bhatia

📖 🐛 + Aatish Bhatia
Aatish Bhatia

📖 🐛 💡 Mislav Milicevic
Mislav Milicevic

💻 🐛 Yuting Lu
Yuting Lu

📖 Adil Rabbani
Adil Rabbani

💻 🐛 💡 @@ -361,8 +361,8 @@ We recognize all types of contributions. This project follows the [all-contribut Pierre Krafft
Pierre Krafft

🐛 💻 📖 💡 👀 ⚠️ 🔧 Zoë Ingram
Zoë Ingram

📖 - Aidan Nelson
Aidan Nelson

🐛 💻 📖 - Cameron Yick
Cameron Yick

📖 + Aidan Nelson
Aidan Nelson

🐛 💻 📖 💡 + Cameron Yick
Cameron Yick

📖 💡 Tanvi Kumar
Tanvi Kumar

🐛 💻 📖 💡 Katsuya Endoh
Katsuya Endoh

@@ -425,7 +425,7 @@ We recognize all types of contributions. This project follows the [all-contribut Samuel Alarco Cantos
Samuel Alarco Cantos

🌍 DIVYANSHU RAJ
DIVYANSHU RAJ

💻 🐛 📖 - sm7515
sm7515

📖 + sm7515
sm7515

📖 💡 Aditya Rachman Putra
Aditya Rachman Putra

📖 shaharyarshamshi
shaharyarshamshi

🌍 Ayush Jain
Ayush Jain

🌍 @@ -472,7 +472,7 @@ We recognize all types of contributions. This project follows the [all-contribut Keith Tan
Keith Tan

📖 - Berke Özgen
Berke Özgen

🐛 + Berke Özgen
Berke Özgen

🐛 💡 Musab Kılıç
Musab Kılıç

💻 ⚠️ Nicholas Marino
Nicholas Marino

📖 Greg Sadetsky
Greg Sadetsky

💻 @@ -516,7 +516,7 @@ We recognize all types of contributions. This project follows the [all-contribut Kathryn Isabelle Lawrence
Kathryn Isabelle Lawrence

💻 🤔 Joonas Jokinen
Joonas Jokinen

🎨 Ajaya Mati
Ajaya Mati

💻 - Suhas CV
Suhas CV

📖 + Suhas CV
Suhas CV

📖 💡 Sanjay Singh Rajpoot
Sanjay Singh Rajpoot

📖 @@ -524,7 +524,7 @@ We recognize all types of contributions. This project follows the [all-contribut Thomas Herlea
Thomas Herlea

🐛 💻 📖 Simranjeet Singh
Simranjeet Singh

💻 📢 🎨 👀 Rahul Mohata
Rahul Mohata

📖 - Dave Pagurek
Dave Pagurek

💻 ⚠️ + Dave Pagurek
Dave Pagurek

💻 ⚠️ 💡 Leo Kamwathi
Leo Kamwathi

💻 @@ -634,7 +634,7 @@ We recognize all types of contributions. This project follows the [all-contribut UnityOfFairfax
UnityOfFairfax

💻 INARI_DARKFOX
INARI_DARKFOX

💻 James Dunn
James Dunn

🐛 💻 - Malay Vasa
Malay Vasa

🎨 💻 + Malay Vasa
Malay Vasa

🎨 💻 💡 wagedu
wagedu

🐛 Wes Lord
Wes Lord

📖 ⚠️ @@ -681,7 +681,7 @@ We recognize all types of contributions. This project follows the [all-contribut SHIBAHARA Hiroki
SHIBAHARA Hiroki

💻 🌍 siddhant
siddhant

🐛 💻 - Caleb Foss
Caleb Foss

🤔 👀 🔌 + Caleb Foss
Caleb Foss

🤔 👀 🔌 💡 chechenxu
chechenxu

💻 Peter Marsh
Peter Marsh

💻 Ahmet Kaya
Ahmet Kaya

🌍 @@ -696,7 +696,7 @@ We recognize all types of contributions. This project follows the [all-contribut J Wong
J Wong

💻 📖 - Austin Lee Slominski
Austin Lee Slominski

💻 📖 + Austin Lee Slominski
Austin Lee Slominski

💻 📖 💡 Nick Briz
Nick Briz

👀 Ayush Shankar
Ayush Shankar

💻 zelf0
zelf0

📖 @@ -721,7 +721,7 @@ We recognize all types of contributions. This project follows the [all-contribut Aaron Casanova
Aaron Casanova

💻 Adam Smith
Adam Smith

💻 - Acha
Acha

💻 + Acha
Acha

💻 💡 Aditya Siddheshwar
Aditya Siddheshwar

💻 Adwaith D
Adwaith D

💻 æmon
æmon

💻 @@ -743,7 +743,7 @@ We recognize all types of contributions. This project follows the [all-contribut AsukaMinato
AsukaMinato

💻 - Jared Donovan
Jared Donovan

💻 + Jared Donovan
Jared Donovan

💻 💡 beau-muylle
beau-muylle

💻 Yana Agun Siswanto
Yana Agun Siswanto

💻 Benjamin Davies
Benjamin Davies

💻 @@ -796,7 +796,7 @@ We recognize all types of contributions. This project follows the [all-contribut Half Scheidl
Half Scheidl

💻 Ashris
Ashris

💻 Arijit
Arijit

💻 - Urvashi
Urvashi

💻 + Urvashi
Urvashi

💻 💡 José Miguel Tajuelo Garrigós
José Miguel Tajuelo Garrigós

💻 @@ -807,7 +807,7 @@ We recognize all types of contributions. This project follows the [all-contribut Joseph Hong
Joseph Hong

💻 - Jithin KS
Jithin KS

💻 + Jithin KS
Jithin KS

💻 💡 Jason Mandel
Jason Mandel

💻 JoeCastor
JoeCastor

💻 Juan Irache
Juan Irache

💻 @@ -921,7 +921,7 @@ We recognize all types of contributions. This project follows the [all-contribut Garima
Garima

💻 Lakshay Joshi
Lakshay Joshi

💻 - perminder-17
perminder-17

💻 + perminder-17
perminder-17

💻 🐛 📖 💡 🤔 🔌 📆 📣 💬 🔬 Yash Pandey
Yash Pandey

🐛 💻 Aditya Deshpande
Aditya Deshpande

🐛 📖 Alejandro
Alejandro

🐛 💻 @@ -1044,7 +1044,7 @@ We recognize all types of contributions. This project follows the [all-contribut c-dacanay
c-dacanay

🎨 📋 💡 mathewpan2
mathewpan2

💻 cog25
cog25

🌍 - Aarati Akkapeddi
Aarati Akkapeddi

💻 + Aarati Akkapeddi
Aarati Akkapeddi

💻 🤔 Maya Arguelles
Maya Arguelles

💻 @@ -1080,6 +1080,51 @@ We recognize all types of contributions. This project follows the [all-contribut Rajas Samse
Rajas Samse

💻 📖 + Jordan Philyaw
Jordan Philyaw

📖 + oliver thurley
oliver thurley

📖 💻 + Renjie Li
Renjie Li

📖 💻 + Vaivaswat Dubey
Vaivaswat Dubey

💻 + Xin Xin
Xin Xin

📋 📢 🧑‍🏫 🤔 + + + Ashish Karn
Ashish Karn

💻 + Darren Kessner
Darren Kessner

💡 + Animesh Sinha
Animesh Sinha

💡 + Kathryn Lichlyter
Kathryn Lichlyter

💡 + Greg Albers
Greg Albers

💡 + Marco Macarena
Marco Macarena

💡 + + + Kristian Hamilton
Kristian Hamilton

💡 + Keshav Gupta
Keshav Gupta

💡 + Ritesh Patil
Ritesh Patil

💡 + Gabriel Sroka
Gabriel Sroka

💡 + Casey Conchinha
Casey Conchinha

💡 + davidblitz
davidblitz

💡 + + + crh82
crh82

💡 + Aaron Welles
Aaron Welles
💡 + Seyko
Seyko

💻 + Xevi H. Aqeel
Xevi H. Aqeel

💡 🎨 + Greg Stanton
Greg Stanton

🐛 💻 📖 💡 🤔 🔌 📆 📣 💬 🔬 + Bojidar Marinov
Bojidar Marinov

💻 ⚠️ + + + Chloe Yan
Chloe Yan

📖 + Mayank Verma
Mayank Verma

💻 + Lauren Berrios
Lauren Berrios

🤔 + roxi09
roxi09

🤔 + Jackie Liu
Jackie Liu

🤔 + Carrie Wang
Carrie Wang

🤔 + + + Himanshu Kholiya
Himanshu Kholiya

💻 + mclark414
mclark414

🤔 + Mx. Ramsey
Mx. Ramsey

🤔 + Franolich Design
Franolich Design

🐛 💻 + Vik
Vik

💻 🐛 🌍 + Qingfeng Huang
Qingfeng Huang

🌍 diff --git a/contributor_docs/README.md b/contributor_docs/README.md index 670c00f91f..f48328af37 100644 --- a/contributor_docs/README.md +++ b/contributor_docs/README.md @@ -36,7 +36,7 @@ Head over to [this link](./contributor_guidelines.md) where you will be guided o Most of the time we will stick with this workflow quite strictly and, especially if you have contributed to other projects before, it may feel like there are too many hoops to jump through for what may be a simple contribution. However, the steps above are aimed to make it easy for you as a contributor and for stewards/maintainers to contribute meaningfully, while also making sure that you won't be spending time working on things that may not be accepted for various reasons. The steps above will help ensure that any proposals or fixes are adequately discussed and considered before any work begin, and often this will actually save you (and the steward/maintainer) time because the PR that would need additional fixing after review, or outright not accepted, would happen less often as a result. -**We see contributing to p5.js as a learning opportunity** and we don't measure sucess by only looking at the volume of contributions we received. There is no time limit on how long it takes you to complete a contribution, so take your time and work at your own pace (we may check in after a long period of inactivity). Ask for help from any of the stewards or maintainers if you need them and we'll try our best to support you. For information related to area stewards or general maintenance of p5.js GitHub repository, please check out the [steward guidelines](./steward_guidelines.md). +**We see contributing to p5.js as a learning opportunity** and we don't measure success by only looking at the volume of contributions we received. There is no time limit on how long it takes you to complete a contribution, so take your time and work at your own pace (we may check in after a long period of inactivity). Ask for help from any of the stewards or maintainers if you need them and we'll try our best to support you. For information related to area stewards or general maintenance of p5.js GitHub repository, please check out the [steward guidelines](./steward_guidelines.md). ## Non-source code contribution There are many more ways to contribute to p5.js through non-source code contribution than can be exhaustively listed here. Some of the ways may also involve working with some of the p5.js repositories (such as adding examples, writing tutorials for the website, etc.). Depending on what the planned contribution is, we may be able to support you in different ways so do reach out to us via any channel available to you (email, social media, [Discourse forum](https://discourse.processing.org/c/p5js/10), Discord, etc). Here are just some ways you can contribute: diff --git a/contributor_docs/archive/es6-adoption.md b/contributor_docs/archive/es6-adoption.md index 4beb93e0f2..76b5ca3e4a 100644 --- a/contributor_docs/archive/es6-adoption.md +++ b/contributor_docs/archive/es6-adoption.md @@ -1,7 +1,7 @@ ## ES6 Adoption p5.js has recently adopted the ECMAScript 2015 (ES6) language specifications in order to reduce the complexity of the codebase, increase readability, and utilize features that facilitate elegant and effective coding practices for both newcomers and seasoned contributors. -The transition process was initially [discussed](https://github.com/processing/p5.js/issues/3758) with the aim of migrating p5 to ES6, which later lead to a series of widespread syntactical changes in the codebase aligned with ES6 specifications. More info on the initial transition can be found [here](https://github.com/processing/p5.js/pull/3874). These changes consisted of minor modifications to the build system to facilitate processing, linting and testing the library based on ES6 standards, as well as major and ubiquitous syntactical modification in line with ES6 features. +The transition process was initially [discussed](https://github.com/processing/p5.js/issues/3758) with the aim of migrating p5 to ES6, which later led to a series of widespread syntactical changes in the codebase aligned with ES6 specifications. More info on the initial transition can be found [here](https://github.com/processing/p5.js/pull/3874). These changes consisted of minor modifications to the build system to facilitate processing, linting and testing the library based on ES6 standards, as well as major and ubiquitous syntactical modification in line with ES6 features. It is worthy to note that as of writing this, these transformations are by no means complete, and do not reflect nor implement every possible feature of ES6. They are intended to facilitate a smoother transition to properly and efficiently utilize ES6 features if and when aligned with the community interests and standards. And serve to motivate contributors to gradually conform to the new style and features. diff --git a/contributor_docs/contributing_to_the_p5js_reference.md b/contributor_docs/contributing_to_the_p5js_reference.md index 849bfef6bf..770188b8b6 100644 --- a/contributor_docs/contributing_to_the_p5js_reference.md +++ b/contributor_docs/contributing_to_the_p5js_reference.md @@ -117,7 +117,7 @@ If the parameter is optional, add square brackets around the name: ### Additional info: Constants -If the parameter takes one or more values defined in [`constants.js`](https://github.com/processing/p5.js/blob/main/src/core/constants.js) , then the type should be specified as `{Constant}` and the valid values should be enumerated in the comment following the `either` keyword, e.g.: +If the parameter takes one or more values defined in [`constants.js`](https://github.com/processing/p5.js/blob/main/src/core/constants.js), then the type should be specified as `{Constant}` and the valid values should be enumerated in the comment following the `either` keyword, e.g.: ``` @param {Constant} horizAlign horizontal alignment, either LEFT, CENTER, or RIGHT @@ -227,7 +227,7 @@ The relevant `@example` tag to create the above is as follows: After the `@example` tag, you should start an HTML `
` tag followed by a `` tag. In between the opening and closing `` tag, you will insert the relevant example code. The basic principle of writing good example code for the reference is to keep things simple and minimal. The example should be meaningful and explain how the feature works without being too complicated. The example’s canvas should be 100x100 pixels and if the `setup()` function is not included, such as in the example above, the code will be automatically wrapped in a `setup()` function with a default 100x100 pixels gray background canvas created. We won’t go through the details about best practices and code style for the example code here; please see the reference style guide instead. -You can have multiple examples for one feature.To do so, add an additional `
` and `` HTML block right after the first closed, separated by a blank line. +You can have multiple examples for one feature. To do so, add an additional `
` and `` HTML block right after the first closed, separated by a blank line. ``` * @example diff --git a/contributor_docs/contributor_guidelines.md b/contributor_docs/contributor_guidelines.md index e2f28310f2..84685141db 100644 --- a/contributor_docs/contributor_guidelines.md +++ b/contributor_docs/contributor_guidelines.md @@ -194,7 +194,7 @@ When opening a discussion issue, you can use the "Labels" panel on the side pane ## Prerequisites -To proceed you should be minimally familiar with working with the command line, git, node.js (at least v20 and up), and have a local development environment setup. +To proceed you should be minimally familiar with working with the command line, git, node.js (at least v18 and up), and have a local development environment setup. ## Introduction @@ -422,7 +422,7 @@ p5.js' code standard or code style is enforced by [ESLlint](https://eslint.org/) While working on any features of p5.js, it is important to keep in mind the design principles of p5.js. Our priorities may differ from the priorities of other projects, so if you are coming from a different project, we recommend that you familiarize yourself with p5.js' design principles. -- **Access** We prioritize accessibility first and foremost, and decisions we make must take into account how it increases access to historically marginalized groups. Read more about this in our access statement. +- **Access** We prioritize accessibility first and foremost, and decisions we make must take into account how they increase access to historically marginalized groups. Read more about this in our access statement. - **Beginner Friendly** The p5.js API aims to be friendly to beginner coders, offering a low barrier to creating interactive and visual web content with cutting-edge HTML5/Canvas/DOM APIs. - **Educational** p5.js is focused on an API and curriculum that supports educational use, including a complete reference to the API with supporting examples, as well as tutorials and sample class curricula that introduce core creative coding principles in a clear and engaging order. - **JavaScript and its community** p5.js aims to make web development practices more accessible to beginners by modeling proper JavaScript design patterns and usage while abstracting them where necessary. As an open-source library, p5.js also includes the wider JavaScript community in its creation, documentation, and dissemination. diff --git a/contributor_docs/creating_libraries.md b/contributor_docs/creating_libraries.md index 0ee2c04539..a7f2caa2ae 100644 --- a/contributor_docs/creating_libraries.md +++ b/contributor_docs/creating_libraries.md @@ -279,7 +279,7 @@ Your addon library may not extend p5 or p5 classes at all, but instead just offe **p5.js has two modes, global mode and instance mode.** In global mode, all p5 properties and methods are bound to the `window` object, allowing users to call methods like `background()` without having to prefix them with anything. However, this means you need to be careful not to overwrite native JavaScript functionality. For example “`Math`” and “`console`” are both native Javascript functionalities so you shouldn’t have methods named “`Math`” or “`console`”. -**Class names should use** `PascalCase`**, while methods and properties should use** `camelCase`**.** Classes in p5 are prefixed with p5. We would like to keep this namespace for p5 core classes only, so when you create your own namespace, **do not include the** `p5.` **prefix for class names**. You are welcomed to create your own prefix, or just give them non-prefixed names. +**Class names should use** `PascalCase`**, while methods and properties should use** `camelCase`**.** Classes in p5 are prefixed with p5. We would like to keep this namespace for p5 core classes only, so when you create your own namespace, **do not include the** `p5.` **prefix for class names**. You are welcome to create your own prefix, or just give them non-prefixed names. ```js // Do not do this @@ -307,4 +307,4 @@ p5.prototype.myMethod = function(){ **Examples are great, too!** They show people what your library can do. Because this is all JavaScript, people can see them running online before they download anything.[ ](http://jsfiddle.net/) You can create a collection of examples on the p5.js web editor to showcase how your library works. -**Submit your library!** Once your library is ready for distribution and you’d like it included on the [p5js.org/libraries](https://p5js.org/libraries) page, please submit a pull request on the p5.js website GitHub repository following [this intruction](https://github.com/processing/p5.js-website/blob/main/docs/contributing_libraries.md)! \ No newline at end of file +**Submit your library!** Once your library is ready for distribution and you’d like it included on the [p5js.org/libraries](https://p5js.org/libraries) page, please submit a pull request on the p5.js website GitHub repository following [this intruction](https://github.com/processing/p5.js-website/blob/main/docs/contributing_libraries.md)! diff --git a/contributor_docs/documentation_style_guide.md b/contributor_docs/documentation_style_guide.md index 8e42b45116..be6a48ddda 100644 --- a/contributor_docs/documentation_style_guide.md +++ b/contributor_docs/documentation_style_guide.md @@ -140,7 +140,7 @@ Always use `let` to declare variables. **Accessibility terminology** -The following terminiology is adapted from the WordPress documentation guidelines for [Writing inclusive documentation](https://make.wordpress.org/docs/style-guide/general-guidelines/inclusivity/#accessibility-terminology). For more background on people-first language, see the CDC's guide on [Communicating With and About People with Disabilities](https://www.cdc.gov/ncbddd/disabilityandhealth/materials/factsheets/fs-communicating-with-people.html). +The following terminology is adapted from the WordPress documentation guidelines for [Writing inclusive documentation](https://make.wordpress.org/docs/style-guide/general-guidelines/inclusivity/#accessibility-terminology). For more background on people-first language, see the CDC's guide on [Communicating With and About People with Disabilities](https://www.cdc.gov/ncbddd/disabilityandhealth/materials/factsheets/fs-communicating-with-people.html). | Recommended | Not Recommended | | -- | -- | @@ -713,7 +713,7 @@ if ( ## Iteration -- Don’t use a `while` or `do-while` loops unless it's necessary. Use `for` loops to iterate a fixed number of times. +- Don’t use `while` or `do-while` loops unless it's necessary. Use `for` loops to iterate a fixed number of times. ```javascript let numPetals = 7; @@ -896,7 +896,7 @@ for (let i = 0; i < numbers.length; i += 1) { let numbersCopy = numbers.slice(); ``` -- Write arrays on multiple lines when it improves readibility. Use line breaks after the opening bracket and before the closing bracket. Add a trailing comma. +- Write arrays on multiple lines when it improves readability. Use line breaks after the opening bracket and before the closing bracket. Add a trailing comma. ```javascript // Bad. diff --git a/contributor_docs/friendly_error_system.md b/contributor_docs/friendly_error_system.md index c237cbcf40..185f9f1448 100644 --- a/contributor_docs/friendly_error_system.md +++ b/contributor_docs/friendly_error_system.md @@ -74,7 +74,7 @@ The basic format of a translation file's item has a key and a value (message) in ```json { "key": "value" } ``` -For example, we have a ASCII logo saved in this format: +For example, we have an ASCII logo saved in this format: ```json "logo": " _ \n /\\| |/\\ \n \\ ` ' / \n / , . \\ \n \\/|_|\\/ \n\n" ``` diff --git a/contributor_docs/how-to-add-friendly-error-messages.md b/contributor_docs/how-to-add-friendly-error-messages.md index 4b945c899d..7fc37ce499 100644 --- a/contributor_docs/how-to-add-friendly-error-messages.md +++ b/contributor_docs/how-to-add-friendly-error-messages.md @@ -163,7 +163,7 @@ Next, you will file an issue ticket to discuss creating a new case or confirm yo Go to the [issue board](https://github.com/processing/p5.js/issues), press the "New Issue" button, and then choose the "Issue: 💡 Existing Feature Enhancement" option. An empty form should appear. -Add a title along the lines of “Adding a new case to `fileLoadErrrorCases`: \[a high-level description of your file load error case].” For the “Increasing access” section, enter a short paragraph on the typical scenario you prepared at the beginning of this step. +Add a title along the lines of “Adding a new case to `fileLoadErrorCases`: \[a high-level description of your file load error case].” For the “Increasing access” section, enter a short paragraph on the typical scenario you prepared at the beginning of this step. Then, check the “Friendly Errors” box for the “Most appropriate sub-area of p5.js?” question. Lastly, for the “Feature enhancement details” section, enter your paragraph detailing your error handling and what file types it loads. diff --git a/contributor_docs/method.example.js b/contributor_docs/method.example.js index fcc6c82583..67c4e0fb96 100644 --- a/contributor_docs/method.example.js +++ b/contributor_docs/method.example.js @@ -2,7 +2,7 @@ * "This is a template for inline documentation of a method. Remove all text * between double quotes for using this template. Some description about the * method goes here. Explain in simple words, what the function does and what - * would be good/bad use cases for it. If there are any corners cases or warnings, + * would be good/bad use cases for it. If there are any corner cases or warnings, * do explain them over here." * * By default, the background is transparent. @@ -32,8 +32,8 @@ * "A single line precisely describing the second example" */ -// "If your method has more than one signatures, they can be documentated each -// in their own block with description about their parameters as follows." +// "If your method has more than one signature, they can be documented each +// in their own block with description of their parameters as follows." /** * @method "methodName" * @param {"dataType"} "paramName" "Description of the param" diff --git a/contributor_docs/project_wrapups/orenshoham_gsoc_2019.md b/contributor_docs/project_wrapups/orenshoham_gsoc_2019.md index c9332e44a2..a5008a83d5 100644 --- a/contributor_docs/project_wrapups/orenshoham_gsoc_2019.md +++ b/contributor_docs/project_wrapups/orenshoham_gsoc_2019.md @@ -8,9 +8,9 @@ The AudioWorklet API consists of two classes: [AudioWorkletProcessor](https://de AudioWorklet replaces [ScriptProcessorNode](https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode), a now-deprecated Web Audio node that runs audio code in the browser's main thread. p5.js-sound used ScriptProcessorNode internally in three classes: -- [p5.SoundFile](https://p5js.org/reference/#/p5.SoundFile), which used a ScriptProcessorNode to keep track of a SoundFile's current playback position. -- [p5.Amplitude](https://p5js.org/reference/#/p5.Amplitude), which used a ScriptProcessorNode to perform amplitude analysis. -- [p5.SoundRecorder](https://p5js.org/reference/#/p5.SoundRecorder), which used a ScriptProcessorNode to concatenate audio buffers together during the recording process. +- [p5.SoundFile](https://p5js.org/reference/p5.SoundFile), which used a ScriptProcessorNode to keep track of a SoundFile's current playback position. +- [p5.Amplitude](https://p5js.org/reference/p5.Amplitude), which used a ScriptProcessorNode to perform amplitude analysis. +- [p5.SoundRecorder](https://p5js.org/reference/p5.SoundRecorder), which used a ScriptProcessorNode to concatenate audio buffers together during the recording process. For each of these classes, I created new AudioWorkletProcessors for [p5.SoundFile](https://github.com/processing/p5.js-sound/blob/4d3a3833de4d30f6770740052a82586444a4482a/src/audioWorklet/soundFileProcessor.js), [p5.Amplitude](https://github.com/processing/p5.js-sound/blob/4d3a3833de4d30f6770740052a82586444a4482a/src/audioWorklet/amplitudeProcessor.js), and [p5.SoundRecorder](https://github.com/processing/p5.js-sound/blob/4d3a3833de4d30f6770740052a82586444a4482a/src/audioWorklet/recorderProcessor.js) that replicated the corresponding ScriptProcessorNode's [onaudioprocess](https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode/onaudioprocess) function. diff --git a/contributor_docs/project_wrapups/sanket_gsoc_2019.md b/contributor_docs/project_wrapups/sanket_gsoc_2019.md index 5dab51a5b9..f90e435b76 100644 --- a/contributor_docs/project_wrapups/sanket_gsoc_2019.md +++ b/contributor_docs/project_wrapups/sanket_gsoc_2019.md @@ -18,7 +18,7 @@ Apart from implementing these functions, I also added unit tests, manual tests, Before and during the Summer of Code, I fixed minor bugs unrelated to my project, which helped me immensely to understand and get around the codebase and the workflow of p5.js. They are listed [here](https://github.com/processing/p5.js/pulls?utf8=%E2%9C%93&q=is%3Apr+author%3Asanketsingh24). -### [lightFalloff()](https://p5js.org/reference/#/p5/lightFalloff) +### [lightFalloff()](https://p5js.org/reference/p5/lightFalloff) This function allows the user to set the attenuation values, which are used in shaders to restrict the spread of light. Earlier, this was a constant value. Now, the artists can use this function to set the value themselves. Implementing this function required me to add three new uniforms, as well as modifying the light shader and light.js. The default was set to 1. ### [emissiveMaterial()](https://github.com/processing/p5.js/pull/3820) diff --git a/contributor_docs/project_wrapups/wong_gsoc_2023.md b/contributor_docs/project_wrapups/wong_gsoc_2023.md index 248e27b5c0..def485d24a 100644 --- a/contributor_docs/project_wrapups/wong_gsoc_2023.md +++ b/contributor_docs/project_wrapups/wong_gsoc_2023.md @@ -31,9 +31,9 @@ Many thanks to my mentors for all their support: Adam Ferriss, Austin Slominski, - [Third pull request](https://github.com/processing/p5.js/pull/6324), replacing the old filters with new shader filters. Status: merged ### Public documentation pages: -- [WEBGL](https://p5js.org/reference/#/p5/WEBGL) - Status: merged, page created -- [filter()](https://p5js.org/reference/#/p5/filter) - Status: merged, page not updated yet -- [createFilterShader()](https://p5js.org/reference/#/p5/createFilterShader) - Status: merged, page not created yet +- [WEBGL](https://p5js.org/reference/p5/WEBGL) - Status: merged, page created +- [filter()](https://p5js.org/reference/p5/filter) - Status: merged, page not updated yet +- [createFilterShader()](https://p5js.org/reference/p5/createFilterShader) - Status: merged, page not created yet ### Performance measuring helpers: diff --git a/contributor_docs/release_process.md b/contributor_docs/release_process.md index b2490e6c75..6c42a5575d 100644 --- a/contributor_docs/release_process.md +++ b/contributor_docs/release_process.md @@ -62,7 +62,7 @@ Once triggered, it will run the following steps: In principle, we try to concentrate as many steps as possible to be run in one place, ie. in the CI environment. If a new step that is only run on release is required, it should probably be defined in the CI workflow and not as part of the build configuration. ## Testing -As the release steps are run in CI, testing them can be difficult. Using [act](https://github.com/nektos/act) to test running of the steps locally is possible (and was how they were tested while being developed) but require some temporary modifications to the workflow definition, we'll roughly document here as the precise steps will likely change over time. +As the release steps are run in CI, testing them can be difficult. Using [act](https://github.com/nektos/act) to test running of the steps locally is possible (and was how they were tested while being developed) but requires some temporary modifications to the workflow definition, we'll roughly document here as the precise steps will likely change over time. The test steps will not run because not all system requirements are present to run the mocha Chrome tests. Some system dependencies will likely be needed to be installed with `apt` before setting up the rest of the environment. Keep an eye on the error messages which should give some information on what packages are missing. diff --git a/contributor_docs/steward_guidelines.md b/contributor_docs/steward_guidelines.md index 466fb9888b..98cbdbebdc 100644 --- a/contributor_docs/steward_guidelines.md +++ b/contributor_docs/steward_guidelines.md @@ -74,12 +74,12 @@ Feature request issues should use the "New Feature Request" issue template. The - Does the feature fit into the project scope and [design principles](./contributor_guidelines.md#software-design-principles) of p5.js? - For example, a request to add a new drawing primitive shape may be considered, but a request to adopt a browser-based IOT protocol will likely be out of scope. - Overall, the scope of p5.js should be relatively narrow in order to avoid excessive bloat from rarely used features. - - If a feature does not fit into the scope of p5.js, suggest that the issue author implement the feature as as an addon library. + - If a feature does not fit into the scope of p5.js, suggest that the issue author implement the feature as an addon library. - If it is unclear whether or not it fits, it can be a good idea to suggest making an addon library as a proof-of-concept. This helps give users a way to use the feature, provides a much more concrete example of its usage and importance, and does not necessarily need to be as complete of a solution as a fully integrated feature. It can be integrated into the core of p5.js later if appropriate. - Is the feature likely to cause a breaking change? - Will it conflict with existing p5.js functions and variables? - Will it conflict with typical sketches already written for p5.js? - - Features that are likely to cause conflicts such as the ones above are considered breaking changes. Without a [major version release](https://docs.npmjs.com/about-semantic-versioning), we should not make breaking changes to p5.js. + - Features that are likely to cause conflicts such as the ones above are considered breaking changes. Without a [major version release](https://docs.npmjs.com/about-semantic-versioning), we should not make breaking changes to p5.js. - Can the proposed new feature be achieved using existing functionalities already in p5.js, relatively simple native JavaScript code, or existing easy-to-use libraries? - For example, instead of providing a p5.js function to join an array of strings such as `join(["Hello", "world!"])`, the native JavaScript `["Hello", "world!"].join()` should be preferred instead. 3. If the access requirement and other considerations have been fulfilled, at least two stewards or maintainers must approve the new feature request before work should begin toward a PR. The PR review process for new features is documented below. @@ -119,7 +119,7 @@ Almost all code contributions to the p5.js repositories happen through pull requ ### Simple fix -Simple fixes, such as a small typo fix, can be merged directly by anyone with merge access. Check on the PR "Files Changed" tab to ensure that the automated CI test passes. +Simple fixes, such as a small typo fix, can be merged directly by anyone with merge access. Check on the PR "Files Changed" tab to ensure that the automated CI test passes. ![The "files changed" tab when viewing a pull request on GitHub](images/files-changed.png) @@ -223,7 +223,7 @@ grunt.registerTask('build', [ ]); ``` -Tasks that start with `browserify` are defined in [../tasks/build/browserify.js](../tasks/build/browserify.js). They all similar steps with minor differences. These are the main steps to build the full p5.js library from its many source code files into one: +Tasks that start with `browserify` are defined in [../tasks/build/browserify.js](../tasks/build/browserify.js). They all have similar steps with minor differences. These are the main steps to build the full p5.js library from its many source code files into one: - `browserify` builds p5.js while `browserify:min` builds an intermediate file to be minified in the next step. The difference between `browserify` and `browserify:min` is that `browserify:min` does not contain data needed for FES to function. - `uglify` takes the output file of `browserify:min` and minify it into the final p5.min.js (configuration of this step is in the main Gruntfile.js). diff --git a/contributor_docs/unit_testing.md b/contributor_docs/unit_testing.md index 869c36daa4..a20758faff 100644 --- a/contributor_docs/unit_testing.md +++ b/contributor_docs/unit_testing.md @@ -249,6 +249,10 @@ visualSuite('3D Model rendering', function() { }); ``` +## Visual tests in p5.js 2.0 + +_Both p5.js 1.x and p5.js 2.0 include visual tests. In p5.js 2.0, there are more tests, and the visual testing system uses a new diffing algorithm that is more robust. This section is this p5.js 2.0 specific system._ + Different operating systems and browsers render graphics with subtle variations. These differences are normal and shouldn't cause tests to fail. Common acceptable differences include: @@ -320,4 +324,4 @@ When creating visual tests for p5.js, following these practices will help ensure p5.line(10, 25, 40, 25); screenshot(); // Screenshot with thick lines }); - ``` \ No newline at end of file + ``` diff --git a/contributor_docs/zh-Hans/documentation_style_guide.md b/contributor_docs/zh-Hans/documentation_style_guide.md new file mode 100644 index 0000000000..ae741eb8c0 --- /dev/null +++ b/contributor_docs/zh-Hans/documentation_style_guide.md @@ -0,0 +1,1246 @@ + + +# 文档风格指南 + +你好!欢迎来到 p5.js 文档编写指南。本文档是以下资源的混合: + +- Ruby on Rails [API 文档指南](https://guides.rubyonrails.org/api_documentation_guidelines.html) (CC BY-SA 4.0) +- WordPress 关于[可访问性](https://make.wordpress.org/docs/style-guide/general-guidelines/accessibility/)和[包容性](https://make.wordpress.org/docs/style-guide/general-guidelines/inclusivity/)的文档指南 (CC0) +- Airbnb [JavaScript 风格指南](https://airbnb.io/javascript/) (MIT) + +我们的社区庞大而多样。许多人使用 p5.js 学习编程,其中很大一部分是 K-12 年级的学生。阅读本指南后,你将了解: +- 如何编写有效、包容和易于访问的文档。 +- 如何为文档编写简单的代码示例。 + +## 目录 + +### 写作 +- [YUIDoc](#yuidoc) +- [英语](#英语) +- [牛津逗号](#牛津逗号) +- [措辞](#措辞) +- [无偏见的文档](#无偏见的文档) +- [可访问性和残障](#可访问性和残障) + +### 代码 +- [代码示例](#代码示例) +- [注释](#注释) +- [空白](#空白) +- [分号](#分号) +- [命名约定](#命名约定) +- [变量](#变量) +- [字符串](#字符串) +- [布尔运算符](#布尔运算符) +- [条件语句](#条件语句) +- [迭代](#迭代) +- [对象](#对象) +- [数组](#数组) +- [函数](#函数) +- [箭头函数](#箭头函数) +- [链式调用](#链式调用) +- [类](#类) +- [资源](#资源) + +## YUIDoc + +我们使用 YUIDoc 来生成 p5.js API 文档。要生成文档,请切换到 p5.js 根目录,运行 `npm install`,然后执行: + +``` +$ npm run grunt yui:dev +``` + +输出将出现在 docs/reference 目录中。更多信息请参考[内联文档指南](./contributing_to_the_p5js_reference.md)。 + +**[⬆ 返回顶部](#目录)** + +## 英语 + +请使用美式英语(color、center、modularize 等)。参见[美式和英式英语拼写差异列表](https://en.wikipedia.org/wiki/American_and_British_English_spelling_differences)。 + +**[⬆ 返回顶部](#目录)** + +## 牛津逗号 + +请使用[牛津逗号](https://en.wikipedia.org/wiki/Serial_comma)("red, white, and blue",而不是"red, white and blue")。 + +**[⬆ 返回顶部](#目录)** + +## 措辞 + +写简单、陈述性的句子。简洁是加分项:直奔主题。 + +使用现在时态:"Returns an object that...",而不是"Returned an object that..."或"Will return an object that..."。 + +注释以大写字母开头。遵循常规标点规则: + +```javascript +// Draws a fractal from a Julia set. +function drawFractal(c, radius, maxIter) { + // ... +} +``` + +明确和隐式地传达当前的做事方式。使用本指南中推荐的惯用语。如果需要,重新排序部分以强调首选方法。文档应该是最佳实践的典范,并且对初学者友好。 + +文档必须简洁但全面。探索并记录边缘情况。每种参数组合会发生什么?初学者的代码中最可能出现哪些错误? + +正确拼写名称:p5.js、CSS、HTML、JavaScript、WebGL。如有疑问,请参考官方文档等权威来源。 + +**[⬆ 返回顶部](#目录)** + +## 无偏见的文档 + +编写文档时不要对任何类型的人有偏见。在记录特别要求高/敏感的主题时,花时间自己学习一下。确保你的写作不会无意中伤害或冒犯他人。 + +在编写无偏见的文档时: + +- 包容所有性别认同和表达、性取向、种族、民族、语言、神经类型、体型、残障、阶级、宗教、文化、亚文化、政治观点、年龄、技能水平、职业和背景。使示例像我们的社区一样多样化。 +- 避免政治化内容。如果政治内容是必要的,保持中立。 +- 遵循可访问性指南。 +- 避免会侮辱或伤害人们的内容。 +- 不要对人们、国家和文化做任何概括。这包括正面或中立的概括。 +- 不要编写针对少数群体的偏见和歧视性内容。 +- 避免与历史事件相关的术语。 + +优先使用避免"you"和"your"的措辞。例如,不要: + +``` +If you need to declare a variable, it is recommended that you use `let`. +``` + +而是使用这种风格: + +``` +Always use `let` to declare variables. +``` + +**代词** + +| 推荐 | 不推荐 | +| -- | -- | +| they | he or she | +| them | him or her | +| their | his or her | +| theirs | his or hers | +| themselves | himself or herself | + +**[⬆ 返回顶部](#目录)** + +## 可访问性和残障 + +- 注重读者而不是强调他们的不便。 +- 不要将残障人士称为残疾人。使用[批准的术语](https://make.wordpress.org/docs/style-guide/general-guidelines/inclusivity/#accessibility-terminology)来指代特定残障的人。 +- 在整个 p5.js 文档中保持统一的结构。在风格和视觉上强调重要点。 +- 使用屏幕阅读器测试文档。要测试屏幕阅读器,请参见[屏幕阅读器列表](https://en.wikipedia.org/wiki/List_of_screen_readers)。 +- 考虑所有类型设备和操作系统的多平台可访问性。 +- 创建使用所有类型输入设备的示例,如基于语音和手势的设备、控制器、鼠标和键盘。 +- 不要使用能力歧视语言。在编写关于可访问性和残障的内容时要包容和无偏见。 +- 对 HTML 语义采取实用方法。不要纯粹为了语义而添加语义。如果有明显匹配内容的 HTML 结构,请使用该元素。例如,一组链接很可能应该使用列表元素。 +- 使用简单的表格和表格格式。避免使用 span 标签(如 rowspan 和 colspan)。表格对屏幕阅读器来说很困难。 + +**可访问性术语** + +以下术语改编自 WordPress 文档指南中的[编写包容性文档](https://make.wordpress.org/docs/style-guide/general-guidelines/inclusivity/#accessibility-terminology)。有关以人为本语言的更多背景,请参见 CDC 的[与残障人士沟通指南](https://www.cdc.gov/ncbddd/disabilityandhealth/materials/factsheets/fs-communicating-with-people.html)。 + +| 推荐 | 不推荐 | +| -- | -- | +| 残障人士 | 残疾人、残障、能力不同、有挑战、不正常 | +| 非残障人士 | 正常人、健康人、健全人 | +| 有[残障] | 受害者、遭受、受...影响、被...折磨 | +| 无法说话,使用合成语音 | 哑巴、失语 | +| 聋人,听力低下 | 听力障碍 | +| 盲人,视力低下 | 视力障碍,视觉挑战 | +| 认知或发育障碍 | 智力挑战,学习缓慢 | +| 行动不便的人,身体残障的人 | 瘸子,残障 | + +## 代码示例 + +选择有意义的代码示例,涵盖基础知识以及容易出错的地方。只有在解释功能工作原理时才使用高级语法。当一个圆就能传达想法时,不要画五个圆来解释。代码示例本身应遵循以下指南。 + +**[⬆ 返回顶部](#目录)** + +## 注释 + +- 使用 `//` 进行单行注释。将单行注释放在注释主题上方的新行上。除非是块的第一行,否则在注释前放置一个空行。 + +```javascript +// 不好。 +let magicWord = 'Please'; // 记住这个。 + +// 好。 +// 记住这个。 +let magicWord = 'Please'; + +// 不好。 +if (keyIsPressed === true) { + thing1(); + // 这是一个重要的注释。 + thing2(); +} + +// 好。 +if (keyIsPressed === true) { + thing1(); + + // 这是一个重要的注释。 + thing2(); +} +``` + +- 所有注释都以空格开头,使其更易于阅读。 + +```javascript +// 不好。 +//记住这个。 +let magicWord = 'Please'; + +// 好。 +// 记住这个。 +let magicWord = 'Please'; +``` + +- 使用 `//` 进行多行注释。 + +```javascript + +// 不好。 +/** + * 我将使用 // 进行多行注释。 + * 我将使用 // 进行多行注释。 + * 我将使用 // 进行多行注释。 + * 我将使用 // 进行多行注释。 + * 我将使用 // 进行多行注释。 + */ + +// 不好。 +/* + 我将使用 // 进行多行注释。 + 我将使用 // 进行多行注释。 + 我将使用 // 进行多行注释。 + 我将使用 // 进行多行注释。 + 我将使用 // 进行多行注释。 + */ + +// 好。 +// 我将使用 // 进行多行注释。 +// 我将使用 // 进行多行注释。 +// 我将使用 // 进行多行注释。 +// 我将使用 // 进行多行注释。 +// 我将使用 // 进行多行注释。 + +``` + +**[⬆ 返回顶部](#目录)** + +## 空白 + +- 缩进块 2 个空格。 + +```javascript +// 不好。 +function setup() { +∙∙∙∙createCanvas(400, 400); +} + +// 不好。 +function setup() { +∙createCanvas(400, 400); +} + +// 好。 +function setup() { +∙∙createCanvas(400, 400); +} +``` + +- 在左大括号前放置 1 个空格。 + +```javascript +// 不好。 +function setup(){ + createCanvas(400, 400); +} + +// 好。 +function setup() { + createCanvas(400, 400); +} +``` + +- 在控制语句(如 `if` 和 `for`)中的左括号前放置 1 个空格。在参数列表和函数名之间不要放置空格。 + +```javascript +// 不好。 +if(keyIsPressed === true) { + doStuff (); +} + +// 好。 +if (keyIsPressed === true) { + doStuff(); +} + +// 不好。 +function setup () { + createCanvas (400, 400); +} + +// 好。 +function setup() { + createCanvas(400, 400); +} +``` + +- 在运算符之间放置空格。 + +```javascript +// 不好。 +let y=x+5; + +// 好。 +let y = x + 5; +``` + +## 分号 + +- 使用分号。 + +> 为什么?JavaScript 的[自动分号插入](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion)可能导致细微的错误。 + +```javascript +// 不好。 +let x = 0 + +// 好。 +let x = 0; +``` + +## 命名约定 + +- 避免使用单字母名称。要有描述性。 + +```javascript +// 不好。 +function f(x, y) { + // ... +} + +// 好。 +function vectorField(x, y) { + // ... +} +``` + +- 使用驼峰命名法命名对象、函数和实例。 + +```javascript +// 不好。 +let OBJEcttsssss = {}; + +// 不好。 +let this_is_my_object = {}; + +// 好。 +let thisIsMyObject = {}; +``` + +- 使用帕斯卡命名法命名类。 + +```javascript +// 不好。 +class player { + constructor(name) { + this.name = name; + } +} + +// 好。 +class Player { + constructor(name) { + this.name = name; + } +} +``` + +- 不要使用尾随或前导下划线。 + +> 为什么?JavaScript 没有私有属性或方法。 + +```javascript +// 不好。 +class Spy { + constructor(secret) { + this._secret = secret; + } +} + +// 好。 +class Spy { + constructor(secret) { + this.secret = secret; + } +} +``` + +**[⬆ 返回顶部](#目录)** + +## 变量 + +- 避免使用 `var` 声明变量。 + +> 为什么?使用 `var` 声明的变量具有令人困惑的作用域规则。这些会导致细微的错误。 + +```javascript +// 不好,因为它看起来合理。 +circle(x, y, 50); +var x = 200; +var y = 200; + +// 好,因为它会抛出 ReferenceError。 +circle(x, y, 50); +let x = 200; +let y = 200; +``` + +- 始终使用 `let` 声明变量。避免使用 `const`。 + +> 为什么?使用 `let` 声明的变量比使用 `var` 声明的变量更容易理解。变量在草图中经常被重新赋值,所以默认使用 `let` 很有帮助。 + +```javascript +// 不好。 +flower = '🌸'; +var flower = '🌸'; +const flower = '🌸'; + +// 好。 +let flower = '🌸'; +``` + +- 每个变量或赋值使用一个 `let` 声明。 + +> 为什么?这样更容易阅读和添加新的变量声明。 + +```javascript +// 不好。 +let positions = getPositions(), + startSearch = true, + dragonball = 'z'; + +// 好。 +let positions = getPositions(); +let startSearch = true; +let dragonball = 'z'; +``` + +- 在需要的地方分配变量,并将它们放在合理的位置。 + +> 为什么?`let` 是块作用域而不是函数作用域。 + +```javascript +// 不好 - 不必要的搜索。 +function getCharacter(name = 'default') { + let character = characters.find((c) => c.name === name); + + if (name === 'default') { + return false; + } + + if (character) { + return character; + } + + return false; +} + +// 好。 +function getCharacter(name = 'default') { + if (name === 'default') { + return false; + } + + let character = characters.find((c) => c.name === name); + + if (character) { + return character; + } + + return false; +} +``` + +- 避免使用一元递增和递减(`++`,`--`)。 + +> 为什么?一元递增和递减语句受[自动分号插入](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion)的影响。这可能导致递增或递减值的静默错误。使用像 `num += 1` 这样的语句更新变量也比 `num++` 更具表现力。 + +```javascript +// 不好。 +let num = 1; +num++; +--num; + +// 好。 +let num = 1; +num += 1; +num -= 1; +``` + +**[⬆ 返回顶部](#目录)** + +## 字符串 + +- 使用单引号 `''` 表示字符串。 + +```javascript +// 不好。 +let name = "Hilma af Klint"; + +// 不好 - 模板字面量应包含插值或换行。 +let name = `Hilma af Klint`; + +// 好。 +let name = 'Hilma af Klint'; +``` + +- 不要连接导致行超过 80 个字符的字符串。 + +> 为什么?断开的字符串难以阅读,使代码不易搜索。 + +```javascript +// 不好。 +let essay = 'You see us as you want to see us: \ +in the simplest terms, in the most convenient definitions.'; + +// 不好。 +let essay = 'You see us as you want to see us: ' + + 'in the simplest terms, in the most convenient definitions.'; + +// 好。 +let essay = 'You see us as you want to see us: in the simplest terms, in the most convenient definitions.'; +``` + +- 需要时使用模板字符串而不是连接。 + +> 为什么?模板字符串具有简洁的语法。它们还提供适当的换行和字符串插值功能。 + +```javascript +let name = 'Dave'; + +// 不好。 +text(name + ', this conversation can serve no purpose anymore. Goodbye.' + name, 0, 0); + +// 好。 +text(`${name}, this conversation can serve no purpose anymore. Goodbye.`, 0, 0); +``` + +- 不要在字符串中不必要地转义字符。 + +> 为什么?反斜杠会损害可读性。 + +```javascript +// 不好。 +let bad = '\'this\' \i\s \"quoted\"'; + +// 好。 +let good = 'Air quotes make you look "cool".'; +``` + +**[⬆ 返回顶部](#目录)** + +## 布尔运算符 + +- 使用 `===` 和 `!==` 而不是 `==` 和 `!=`。 + +- 不要使用布尔值的快捷方式。 + +> 为什么?对初学者来说更容易理解。 + +```javascript +// 不好。 +if (mouseIsPressed) { + // ... +} + +// 好。 +if (mouseIsPressed === true) { + // ... +} + +// 不好。 +if (name) { + // ... +} + +// 好。 +if (name !== '') { + // ... +} + +// 不好。 +if (collection.length) { + // ... +} + +// 好。 +if (collection.length > 0) { + // ... +} +``` + +- 除非必要,否则不要使用 `switch` 语句。 + +- 混合运算符时使用括号。唯一的例外是算术运算符 `+`、`-` 和 `**`。 + +> 为什么?这样更容易阅读并避免细微的错误。 + +```javascript +// 不好。 +let huh = a && b < 0 || c > 0 || d + 1 === 0; + +// 好。 +let huh = (a && b < 0) || c > 0 || (d + 1 === 0); + +// 不好。 +if (a || b && c) { + return d; +} + +// 好。 +if (a || (b && c)) { + return d; +} + +// 不好。 +let what = a + b / c * d; + +// 好。 +let what = a + (b / c) * d; +``` + +## 条件语句 + +- 对所有多行块使用大括号。 + +```javascript +// 不好。 +if (mouseIsPressed === true) + circle(mouseX, mouseY, 50); + +// 更好。 +if (mouseIsPressed === true) circle(mouseX, mouseY, 50); + +// 最好。 +if (mouseIsPressed === true) { + circle(mouseX, mouseY, 50); +} +``` + +- 将 `else` 放在前一个 `if` 块的右大括号的同一行。 + +```javascript +// 不好。 +if (mouseIsPressed === true) { + thing1(); + thing2(); +} +else { + thing3(); +} + +// 好。 +if (mouseIsPressed === true) { + thing1(); + thing2(); +} else { + thing3(); +} +``` + +- 在总是执行 `return` 语句的 `if` 块后不要使用 `else` 块。 + +```javascript +// 不好。 +function mouseIsOnLeft() { + if (mouseX < width * 0.5) { + return true; + } else { + return false; + } +} + +// 好。 +function mouseIsOnLeft() { + if (mouseX < width * 0.5) { + return true; + } + + return false; +} +``` + +- 如果条件太长,将每个(分组的)条件放在新行上。逻辑运算符应该开始行。 + +> 为什么?这样更容易阅读。 + +```javascript +// 不好。 +if ((number === 123 || letters === 'abc') && mouseIsPressed === true && keyIsPressed === true) { + doStuff(); +} + +// 好。 +if ( + (number === 123 || letters === 'abc') + && mouseIsPressed === true + && keyIsPressed === true +) { + doStuff(); +} +``` + +- 不要使用选择运算符代替条件语句。 + +```javascript +// 不好。 +refrigeratorIsRunning && goCatchIt(); + +// 好。 +if (refrigeratorIsRunning === true) { + goCatchIt(); +} +``` + +**[⬆ 返回顶部](#目录)** + +## 迭代 + +- 除非必要,否则不要使用 `while` 或 `do-while` 循环。使用 `for` 循环来迭代固定次数。 + +```javascript +let numPetals = 7; + +// 不好。 +let i = 0; +while (i < numPetals) { + ellipse(0, 0, 20, 80); + rotate(PI / numPetals); + i += 1; +} + +// 好。 +for (let i = 0; i < numPetals; i += 1) { + ellipse(0, 0, 20, 80); + rotate(PI / numPetals); +} +``` + +- 不要使用 `for` 循环来迭代数组。 + +> 为什么?纯函数比副作用更容易推理。 + +> 使用 `forEach()` / `map()` / `every()` / `filter()` / `find()` / `findIndex()` / `reduce()` / `some()` / `...` 来迭代数组。使用 `Object.keys()` / `Object.values()` / `Object.entries()` 来生成用于迭代对象的数组。 + +```javascript +let diameters = [50, 40, 30, 20, 10]; + +// 不好。 +for (let i = 0; i < diameters.length; i += 1) { + circle(0, 0, diameters[i]); +} + +// 不好。 +for (let d of diameters) { + circle(0, 0, d); +} + +// 好。 +diameters.forEach((d) => circle(0, 0, d)); +``` + +**[⬆ 返回顶部](#目录)** + +## 对象 + +- 使用字面量语法创建对象。 + +```javascript +// 不好。 +let ball = new Object(); + +// 好。 +let ball = {}; +``` + +- 只对无效标识符的属性使用引号。 + +> 为什么?这样更容易阅读并提高语法高亮。JavaScript 引擎也更容易优化性能。 + +```javascript +// 不好。 +let secretObject = { + 'x': 100, + 'y': 200, + 'top-secret': 'classified', +}; + +// 好。 +let secretObject = { + x: 3, + y: 4, + 'top-secret': 'classified', +}; +``` + +- 使用点表示法访问属性。 + +```javascript +let turtle = { + name: 'Leonardo', + color: 'dodgerblue', + weapon: '🗡️', + food: '🍕', +}; + +// 不好。 +let turtleName = turtle['name']; + +// 好。 +let turtleName = turtle.name; +``` + +- 使用方括号表示法 `[]` 访问带有变量的属性。 + +```javascript +let turtle = { + name: 'Leonardo', + color: 'dodgerblue', + weapon: '🗡️', + food: '🍕', +}; + +function getProp(prop) { + return turtle[prop]; +} + +let turtleName = getProp('name'); +``` + +- 不要使用前导逗号。 + +```javascript +// 不好。 +let mathematician = { + firstName: 'Ada' + , lastName: 'Lovelace' +}; + +// 好。 +let mathematician = { + firstName: 'Ada', + lastName: 'Lovelace', +}; +``` + +- 添加尾随逗号。 + +```javascript +// 不好。 +let artist = { + firstName: 'Lauren', + lastName: 'McCarthy' +}; + +// 好。 +let artist = { + firstName: 'Lauren', + lastName: 'McCarthy', +}; +``` + +**[⬆ 返回顶部](#目录)** + +## 数组 + +- 使用字面量语法创建数组。 + +```javascript +// 不好。 +let images = new Array(); + +// 好。 +let images = []; +``` + +- 使用 [Array#push](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/push) 而不是直接赋值来向数组添加项目。 + +```javascript +let lyrics = []; + +// 不好。 +lyrics[lyrics.length] = 'Little rough around the edges, but I keep it smooth'; + +// 好。 +lyrics.push('Little rough around the edges, but I keep it smooth'); +``` + +- 使用 `slice()` 方法复制数组。 + +```javascript +// 不好。 +let numbersCopy = []; + +for (let i = 0; i < numbers.length; i += 1) { + numbersCopy[i] = numbers[i]; +} + +// 好。 +let numbersCopy = numbers.slice(); +``` + +- 当提高可读性时,在多行上编写数组。在左括号后和右括号前使用换行。添加尾随逗号。 + +```javascript +// 不好。 +let matrix = [[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]; + +// 好。 +let matrix = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], +]; + +// 也好。 +let matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; +``` + +**[⬆ 返回顶部](#目录)** + +## 函数 + +- 使用函数声明而不是命名函数表达式。 + +> 为什么?函数声明有一些陷阱,但对初学者来说更容易理解。 + +```javascript +// 不好。 +let foo = function () { + // ... +}; + +// 不好。 +let foo = () => { + // ... +}; + +// 好。 +function foo() { + // ... +} +``` + +- 使用默认参数语法。不要改变函数参数。 + +```javascript +// 不好。 +function createBall(diameter) { + diameter = diameter || 50; + // ... +} + +// 好。 +function createBall(diameter = 50) { + // ... +} +``` + +- 始终将默认参数放在最后。 + +```javascript +// 不好。 +function drawSpiral(angle = 90, length) { + // ... +} + +// 好。 +function drawSpiral(length, angle = 90) { + // ... +} +``` + +**[⬆ 返回顶部](#目录)** + +## 箭头函数 + +- 对匿名函数使用箭头函数表示法。回调是这种语法的常见用例。 + +> 为什么?语法更简洁。它还创建了一个在 `this` 上下文中执行的函数版本,这通常很有帮助。 + +> 为什么不?如果匿名函数很复杂,将其重写为声明的函数。 + +```javascript +// 不好。 +function setup() { + loadImage('assets/moonwalk.jpg', function (img) { + image(img, 0, 0); + }); +} + +// 好。 +function setup() { + loadImage('assets/moonwalk.jpg', (img) => { + image(img, 0, 0); + }); +} + +// 不好。 +function preload() { + loadImage('assets/moonwalk.jpg', (img) => { + // 复杂的预处理... + }); +} + +// 好。 +function preload() { + loadImage('assets/moonwalk.jpg', processImage); +} + +function processImage(img) { + // 复杂的预处理... +} +``` + +- 尽可能使用隐式返回。如果函数体返回单个语句且没有副作用,则省略大括号。否则,保留大括号并使用 `return` 语句。 + +> 为什么?这样更容易阅读。 + +```javascript +// 不好。 +[1, 2, 3].map((number) => { + let squared = number ** 2; + `${number} squared is ${squared}.`; +}); + +// 不好。 +[1, 2, 3].map((number) => { + let squared = number ** 2; + return `${number} squared is ${squared}.`; +}); + +// 好。 +[1, 2, 3].map((number) => `${number} squared is ${number ** 2}.`); +``` + +- 始终在参数周围包含括号。 + +> 为什么?这样做可以减少更改参数时的错误。 + +```javascript +// 不好。 +[1, 2, 3].map(number => number * number); + +// 好。 +[1, 2, 3].map((number) => number * number); +``` + +**[⬆ 返回顶部](#目录)** + +## 链式调用 + +- 使用单独的函数调用而不是函数链式调用。 + +> 为什么?适应可能不熟悉函数链式调用概念的用户。 + +```javascript +// 不好。 +fill(0) + .strokeWeight(6) + .textSize(20); + +// 不好。 +fill(0).strokeWeight(6).textSize(20); + +// 好。 +fill(0); +strokeWeight(6); +textSize(20); +``` + +**[⬆ 返回顶部](#目录)** + +## 类 + +- 始终使用 `class`。避免直接操作 `prototype`。唯一的例外是解释如何[创建库](./creating_libraries.md)。 + +> 为什么?`class` 语法更简洁,更容易理解。 + +```javascript +// 不好。 +function Mover(x, y, radius) { + this.x = x; + this.y = y; + this.radius = radius; +} + +Mover.prototype.update = function () { + this.x += 1; + this.y += 1; +}; + +Mover.prototype.render = function () { + circle(this.x, this.y, 2 * this.radius); +}; + +// 好。 +class Mover { + constructor(x, y, radius) { + this.x = x; + this.y = y; + this.radius = radius; + } + + update() { + this.x += 1; + this.y += 1; + } + + render() { + circle(this.x, this.y, 2 * this.radius); + } +} +``` + +- 使用 `extends` 进行继承。 + +```javascript +class RandomMover extends Mover { + update() { + this.x += random(-1, 1); + this.y += random(-1, 1); + } +} +``` + +- 确保自定义 `toString()` 方法不会引起副作用。 + +```javascript +// 不好。 +class Mover { + // ... + + toString() { + this.x += 1; + return `Mover at (${this.x}, ${this.y})`; + } +} + +// 好。 +class Mover { + // ... + + toString() { + return `Mover at (${this.x}, ${this.y})`; + } +} +``` + +- 不要编写空的构造函数或仅委托给父类的构造函数。 + +> 为什么?如果未指定,类有默认构造函数。 + +```javascript +// 不好。 +class Dot { + constructor() {} + + render() { + circle(mouseX, mouseY, 50); + } +} + +// 好。 +class Dot { + render() { + circle(mouseX, mouseY, 50); + } +} + +// 不好。 +class DragonBall extends Ball { + constructor(x, y, d) { + super(x, y, d); + } +} + +// 好。 +class DragonBall extends Ball { + constructor(x, y, d, numStars) { + super(x, y, d); + this.numStars = numStars; + } +} +``` + +- 避免重复的类成员。 + +> 为什么?重复的类成员声明优先选择最后一个。有重复通常意味着有错误。 + +```javascript +// 不好。 +class Mover { + // ... + + update() { + this.x += this.xspeed; + this.y += this.yspeed; + } + + update() { + this.x = 0; + this.y = 0; + } +} + +// 好。 +class Mover { + // ... + + update() { + this.x += this.xspeed; + this.y += this.yspeed; + } + + reset() { + this.x = 0; + this.y = 0; + } +} +``` + +**[⬆ 返回顶部](#目录)** + +## 资源 + +- 始终从名为"assets"的文件夹加载资源。 + +> 为什么?它模拟了良好的项目组织。这也是在 p5.js 网站上加载资源所必需的。将资源放在以下文件夹中以将其包含在我们的在线文档中: +- 示例:[src/data/examples/assets](https://github.com/processing/p5.js-website/tree/main/src/data/examples) +- 参考页面:[src/templates/pages/reference/assets](https://github.com/processing/p5.js-website/tree/main/src/templates/pages/reference/assets) +- 学习页面:[src/assets/learn](https://github.com/processing/p5.js-website/tree/main/src/assets/learn) + +```javascript +let img; + +// 不好。 +function preload() { + img = loadImage('moonwalk.jpg'); +} + +// 好。 +function preload() { + img = loadImage('assets/moonwalk.jpg'); +} +``` + +**[⬆ 返回顶部](#目录)** diff --git a/contributor_docs/zh-Hans/fes_contribution_guide.md b/contributor_docs/zh-Hans/fes_contribution_guide.md new file mode 100644 index 0000000000..0f852096ac --- /dev/null +++ b/contributor_docs/zh-Hans/fes_contribution_guide.md @@ -0,0 +1,526 @@ + + +# 友好错误系统贡献指南 + +`core/friendly_errors`文件夹包含了p5js的友好错误系统(FES)代码,该系统负责生成友好错误消息或友好错误。您可能已经在控制台中看到以"`🌸 p5.js says:`"开头的友好错误消息,这些消息是对默认浏览器生成的错误消息的补充。 + +FES包含多个负责生成不同类型错误的友好错误消息的函数。这些函数从各种位置收集错误,包括文件加载错误和自动播放错误的错误处理,库内的参数检查,以及p5.js贡献者实现的其他自定义错误处理。 + +本文档首先概述了FES的主要函数及其位置。在随后的参考部分,您将找到有关这些单独函数的完整信息(描述、语法、参数、位置)。在文档的最后部分,您将找到我们以前的贡献者的笔记(开发笔记),概述了FES的已知限制和可能的未来方向。如果您正在考虑为FES做贡献,请查看[开发笔记](#-开发笔记)! + + +## 概述 + +生成友好错误消息的主要函数是: + +- `p5._friendlyError()`:将输入消息格式化并打印(通过`_report()`)为友好错误 +- `p5._validateParameters()`:验证接收到的输入值是否有错误类型或缺少值 +- `p5._friendlyFileLoadError()`:指导用户解决与文件加载函数相关的错误 +- `p5._friendlyAutoplayError()`:指导用户解决与浏览器自动播放策略相关的错误 + +以下是一个图表,概述了FES中所有函数的位置以及它们如何相互连接: + +![FES中使用的文件及其用途的图表](../images/fes.svg) + +各个文件包含以下主要FES函数: + +- `fes_core.js`:包含`_report()`、`_friendlyError()`和`_friendlyAutoplayError()`,以及用于格式化和测试友好错误的其他辅助函数。 +- `validate_params.js`:包含`_validateParameters()`以及用于参数验证的其他辅助函数。 +- `file_errors.js`:包含`_friendlyFileLoadError()`和用于文件加载错误的其他辅助函数。 +- `browser_errors.js`:包含将使用FES全局错误类(`fes.globalErrors`)生成的浏览器错误列表。 +- `stacktrace.js`:包含解析错误堆栈的代码(借用自[stacktrace.js](https://github.com/stacktracejs/stacktrace.js))。 + + +## 📚 参考:FES函数 + +### `_report()` + +#### 描述 + +`_report()`是直接将错误辅助消息输出到控制台的主要函数。 + +**注意:**如果设置了`p5._fesLogger`(即,我们正在运行测试),则将使用它代替`console.log`。这在我们通过Mocha运行测试时非常有用。在这种情况下,`_fesLogger`将让`_report`将错误消息作为字符串传递给Mocha,该字符串将与断言的字符串进行测试。 + + +#### 语法 + +```js +_report(message); + +_report(message, func); + +_report(message, func, color); +``` + + +#### 参数 + +``` +@param {String} message 要打印的消息 +@param {String} [func] 函数名称 +@param {Number|String} [color] CSS颜色代码 +``` + +`[func]`输入用于在错误消息末尾附加参考链接。 + +`[color]`输入用于设置错误消息的颜色属性。这在当前版本的友好错误消息中未使用。 + + +#### 位置 + +core/friendly\_errors/fes\_core.js + +### `_friendlyError()` + +#### 描述 + +`_friendlyError()`创建并打印友好错误消息。任何p5函数都可以调用此函数来提供友好错误消息。 + +`_friendlyFileLoadError()`位于以下函数内: + +- `image/loading_displaying/loadImage()` +- `io/files/loadFont()` +- `io/files/loadTable()` +- `io/files/loadJSON()` +- `io/files/loadStrings()` +- `io/files/loadXML()` +- `io/files/loadBytes()`。 + +对`_friendlyFileLoadError`的调用序列看起来像这样: + +``` +_friendlyFileLoadError + _report +``` + + +#### 语法 + +```js +_friendlyFileLoadError(errorType, filePath); +``` + + +#### 参数 + +``` +@param {Number} errorType 文件加载错误类型的编号 +@param {String} filePath 导致错误的文件路径 +``` + +`errorType`输入指的是`core/friendly_errors/file_errors.js`中枚举的特定类型的文件加载错误。p5.js中的文件加载错误被分为各种不同的情况。这种分类旨在便于提供与不同错误场景相对应的精确和信息丰富的错误消息。例如,当它无法读取字体文件中的数据时,它可以显示与尝试加载过大无法读取的文件时不同的错误。 + + +#### 示例 + +文件加载错误示例: + +```js +/// 缺少字体文件 +let myFont; +function preload() { + myFont = loadFont('assets/OpenSans-Regular.ttf'); +} +function setup() { + fill('#ED225D'); + textFont(myFont); + textSize(36); + text('p5*js', 10, 50); +} +function draw() {} +``` + +除了浏览器的"不支持"错误外,FES还将在控制台中生成以下消息: + +``` +🌸 p5.js says: 看起来加载字体时出现了问题。请检查文件路径(assets/OpenSans-Regular.ttf)是否正确,尝试在线托管文件,或运行本地服务器。 + ++ 更多信息:https://github.com/processing/p5.js/wiki/Local-server +``` + + +#### 位置 + +/friendly\_errors/file\_errors.js + + +### `_friendlyAutoplayError()` + +#### 描述 + +如果存在与播放媒体(例如视频)相关的错误,`_friendlyAutoplayError()`会在内部调用,这很可能是由于浏览器的自动播放策略。 + +它调用`translator()`使用键`fes.autoplay`生成并打印友好错误消息。您可以在`translations/en/translation.json`中查看所有可用的键。 + + +#### 位置 + +core/friendly\_errors/fes\_core.js + + +### `_validateParameters()` + +#### 描述 + +`_validateParameters()`通过将输入参数与`docs/reference/data.json`中的信息匹配来运行参数验证,该信息是从函数的内联文档创建的。它检查函数调用是否包含正确数量和正确类型的参数。 + +它调用`translator()`使用键`fes.friendlyParamError.*`生成并打印友好错误消息。您可以在`translations/en/translation.json`中查看所有可用的键。 + +可以通过`p5._validateParameters(FUNCT_NAME, ARGUMENTS)`或`p5.prototype._validateParameters(FUNCT_NAME, ARGUMENTS)`在需要参数验证的函数内部调用此函数。建议将静态版本`p5._validateParameters`用于一般用途。`p5.prototype._validateParameters(FUNCT_NAME, ARGUMENTS)`主要用于调试和单元测试。 + +`_validateParameters()`函数位于这些函数内: + +- `accessibility/outputs` +- `color/creating_reading` +- `color/setting` +- `core/environment` +- `core/rendering` +- `core/shape/2d_primitives` +- `core/shape/attributes` +- `core/shape/curves` +- `core/shape/vertex` +- `core/transform` +- `data/p5.TypedDict` +- `dom/dom` +- `events/acceleration` +- `events/keyboard` +- `image/image` +- `image/loading_displaying` +- `image/p5.Image` +- `image/pixel` +- `io/files` +- `math/calculation` +- `math/random` +- `typography/attributes` +- `typography/loading_displaying` +- `utilities/string_functions` +- `webgl/3d_primitives` +- `webgl/interaction` +- `webgl/light` +- `webgl/loading` +- `webgl/material` +- `webgl/p5.Camera` + +从`_validateParameters`的调用序列看起来像这样: + +``` +validateParameters + buildArgTypeCache + addType + lookupParamDoc + scoreOverload + testParamTypes + testParamType + getOverloadErrors + _friendlyParamError + ValidationError + report + friendlyWelcome +``` + + +#### 语法 + +```js +_validateParameters(func, args); +``` + + +#### 参数 + +``` +@param {String} func 被调用的函数的名称 +@param {Array} args 用户输入参数 +``` + + +#### 示例 + +缺少参数的示例: + +```js +arc(1, 1, 10.5, 10); +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: [sketch.js, line 13] arc()至少需要6个参数,但只收到了4个。 (https://p5js.org/reference/p5/arc) +``` + +类型不匹配的示例: + +```js +arc(1, ',1', 10.5, 10, 0, Math.PI); +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: [sketch.js, line 14] arc()的第一个参数需要Number类型,但收到了string类型。 (https://p5js.org/reference/p5/arc) +``` + + +#### 位置 + +core/friendly\_errors/validate\_params.js + + +### `fesErrorMonitor()` + +#### 描述 + +`fesErrorMonitor()`监控浏览器错误消息,猜测错误的来源并为用户提供额外的指导。这包括堆栈跟踪,它是程序中直到抛出错误点为止调用的函数的顺序列表。堆栈跟踪对于确定错误是内部的还是由用户直接调用的某些内容引起的非常有用。 + +它调用`translator()`使用键`fes.globalErrors.*`生成并打印友好错误消息。您可以在`translations/en/translation.json`中查看所有可用的键。 + +以下是通过`fesErrorMonitor()`生成的错误消息的综合列表: + +- 使用键的友好错误消息:`fes.globalErrors.syntax.*`、`fes.globalErrors.reference.*`、`fes.globalErrors.type.*`。 +- 通过`processStack()`使用键的"内部库"错误消息:`fes.wrongPreload`、`fes.libraryError`。 +- 通过`printFriendlyStack()`使用键的堆栈跟踪消息:`fes.globalErrors.stackTop`、`fes.globalErrors.stackSubseq`。 +- 通过`handleMisspelling()`使用键的拼写检查消息(来自引用错误):`fes.misspelling`。 + +`_fesErrorMonitor()`由`window`上的`error`事件和未处理的承诺拒绝(`unhandledrejection`事件)自动触发。但是,可以在catch块中手动调用,如下所示: + +```js +try { someCode(); } catch(err) { p5._fesErrorMonitor(err); } +``` + +该函数目前适用于`ReferenceError`、`SyntaxError`和`TypeError`的子集。您可以在`browser_errors.js`中找到支持的错误的完整列表。 + +`_fesErrorMonitor`的调用序列大致如下: + +``` + _fesErrorMonitor + processStack + printFriendlyError + (if type of error is ReferenceError) + _handleMisspelling + computeEditDistance + _report + _report + printFriendlyStack + (if type of error is SyntaxError、TypeError, etc) + _report + printFriendlyStack +``` + + +#### 语法 + +```js +fesErrorMonitor(event); +``` + + +#### 参数 + +``` +@param {*} e 错误事件 +``` + + +#### 示例 + +内部错误示例1: + +```js +function preload() { + // 由于在preload中调用background() + // 导致错误 + background(200); +} +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: [sketch.js, line 8] 当调用"background"时,p5js库内部发生了一个错误,错误信息为"无法读取未定义的属性(正在读取'background')"。如果没有特别说明,这可能是由于从preload调用"background"导致的。preload函数中除了加载调用(loadImage、loadJSON、loadFont、loadStrings等)之外,不应该有任何其他内容。 (https://p5js.org/reference/p5/preload) +``` + +内部错误示例2: + +```js +function setup() { + cnv = createCanvas(200, 200); + cnv.mouseClicked(); +} +``` + +FES将在控制台中生成以下消息: + +```js +🌸 p5.js says: [sketch.js, line 12] 当调用mouseClicked时,p5js库内部发生了一个错误,错误信息为"无法读取未定义的属性(正在读取'bind')"。如果没有特别说明,这可能是传递给mouseClicked的参数问题。 (https://p5js.org/reference/p5/mouseClicked) +``` + +错误示例(作用域): + +```js +function setup() { + let b = 1; +} +function draw() { + b += 1; +} +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: + +[sketch.js, line 5] 当前作用域中未定义"b"。如果您已在代码中定义了它,应检查其作用域、拼写和大小写(JavaScript区分大小写)。 + ++ 更多信息:https://p5js.org/examples/data-variable-scope.html +``` + +错误示例(拼写): + +```js +function setup() { + xolor(1, 2, 3); +} +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: [sketch.js, line 2] 您可能不小心写了"xolor"而不是"color"。如果您希望使用p5.js中的函数,请将其更正为color。 (https://p5js.org/reference/p5/color) +``` + + +#### 位置 + +core/friendly\_errors/fes\_core.js + + +### `checkForUserDefinedFunctions()` + +#### 描述 + +检查是否有任何用户定义的函数(`setup()`、`draw()`、`mouseMoved()`等)带有大小写错误。 + +它调用`translator()`使用键`fes.checkUserDefinedFns`生成并打印友好错误消息。您可以在`translations/en/translation.json`中查看所有可用的键。 + + +#### 语法 + +```js +checkForUserDefinedFunctions(context); +``` + + +#### 参数 + +``` +@param {*} context 当前默认上下文。 + 在"全局模式"下设置为window, + 在"实例模式"下设置为p5实例 +``` + + +#### 示例 + +```js +function preload() { + loadImage('myimage.png'); +} +``` + +FES将在控制台中生成以下消息: + +``` +🌸 p5.js says: 您可能不小心写了preLoad而不是preload。如果这不是有意的,请更正它。 (https://p5js.org/reference/p5/preload) +``` + + +#### 位置 + +/friendly\_errors/fes\_core.js + + +### `helpForMisusedAtTopLevelCode()` + +#### 描述 + +`helpForMisusedAtTopLevelCode()`在窗口加载时由`fes_core.js`调用,以检查在`setup()`或`draw()`之外使用p5.js函数的情况。 + +它调用`translator()`使用键`fes.misusedTopLevel`生成并打印友好错误消息。您可以在`translations/en/translation.json`中查看所有可用的键。 + + +#### 参数 + +``` +@param {*} err 错误事件 +@param {Boolean} log false +``` + + +#### 位置 + +/friendly\_errors/fes\_core.js + + +## 💌 开发笔记 + +### 已知限制 + +#### 假阳性与假阴性情况 + +在FES中,您可能会遇到两种类型的错误:假阳性和假阴性。把假阳性想象成虚假警报。当FES警告您有错误,但您的代码实际上是正确的时,就会出现这种情况。另一方面,假阴性就像遗漏了一个错误。当您的代码中有错误,但FES没有提醒您时,就会发生这种情况。 + +识别和修复这些错误很重要,因为它们可以节省调试时间,减少混淆,并使修复实际问题变得更容易。 + +在某些不理想的情况下,错误处理的设计可能需要选择消除假阳性或假阴性。如果必须选择,通常最好消除假阳性。这样,您可以避免生成可能分散注意力或误导用户的不正确警告。 + + +#### 与`fes.GlobalErrors`相关的限制 + +FES只能检测到使用`const`或`var`声明的被覆盖的全局变量。使用let声明的变量不会被检测到。这个限制是由于`let`处理变量实例化的特定方式导致的,目前无法解决。 + +`fesErrorMonitor()`下描述的功能目前仅在Web编辑器上或在本地服务器上运行时有效。有关更多详情,请参见 pull request \[[#4730](https://github.com/processing/p5.js/pull/4730)]。 + + +### FES的性能问题 + +默认情况下,p5.js启用FES,而在`p5.min.js`中禁用,以防止FES函数减慢进程。错误检查系统可能会显著减慢您的代码(在某些情况下最多慢10倍)。请参见[友好错误性能测试](https://github.com/processing/p5.js-website/tree/main/src/assets/learn/performance/code/friendly-error-system)。 + +您可以在草图顶部使用一行代码禁用FES: + +```js +p5.disableFriendlyErrors = true; // 禁用FES +function setup() { + // 进行设置操作 +} +function draw() { + // 进行绘制操作 +} +``` + +请注意,此操作将禁用已知会降低性能的FES某些功能,例如参数检查。但是,不影响性能的友好错误消息仍将启用。这包括在文件加载失败时提供详细的错误消息,或者在您尝试覆盖全局空间中的p5.js函数时显示警告。 + + +### 未来工作的想法 + +- 解耦FES \[[#5629](https://github.com/processing/p5.js/issues/5629)] +- 消除假阳性情况 +- 识别假阴性情况 +- 添加更多单元测试以获得全面的测试覆盖 +- 更直观、清晰且可翻译的消息。关于友好错误国际化的更多讨论,请查看[友好错误i18n手册](https://almchung.github.io/p5-fes-i18n-book/en/)。 +- 识别更多常见错误类型并使用FES进行泛化(例如 `bezierVertex()`、`quadraticVertex()` - 必需对象未初始化;检查 `nf()`、`nfc()`、`nfp()`、`nfs()` 的Number参数是否为正) + + +## 结论 + +在本README文档中,我们概述了`core/friendly_errors`文件夹的结构。本节解释了这个文件夹的组织和目的,使其更容易导航和理解。此外,对于此文件夹中的每个函数,我们都提供了参考指南。 + +在本文档的后半部分,我们包含了以前贡献者的笔记,讨论了FES的当前限制和未来开发中可能的改进领域。 + +此外,我们很高兴通过2021-2022年进行的FES调查分享来自我们社区的见解。调查结果有两种格式可供查阅: + +- [21-22 FES调查报告漫画](https://almchung.github.io/p5jsFESsurvey/) +- [21-22 FES调查完整报告](https://observablehq.com/@almchung/p5-fes-21-survey)。 + + + \ No newline at end of file diff --git a/contributor_docs/zh-Hans/how-to-add-friendly-error-messages.md b/contributor_docs/zh-Hans/how-to-add-friendly-error-messages.md new file mode 100644 index 0000000000..bd51c80acd --- /dev/null +++ b/contributor_docs/zh-Hans/how-to-add-friendly-error-messages.md @@ -0,0 +1,316 @@ + + +# 如何添加友好错误信息 + +本指南将引导您完成使用友好错误系统(FES,🌸)编写友好错误(FE)信息的步骤。如果您的新方法支持自定义错误处理或为用户输出自定义日志,您可能需要为其编写友好错误信息。所有这些信息都是通过基于[i18next](https://www.i18next.com/)的`translator()`方法动态生成的,这使得p5.js能够提供与用户环境匹配的错误信息翻译。 + + +## ❗️`p5.min.js`中没有翻译 + +- 我们已将 \[i18next] 集成到我们的代码库中。但是,它的使用仅限于p5.js的未压缩版本。压缩版本`p5.min.js`仅包含我们国际化代码的基本框架,不包含实际实现。 +- 在Browserify构建任务和`src/core/init.js`中,有特定的逻辑来避免在压缩版本中加载或设置翻译。因此,添加翻译不会影响`p5.min.js`的大小。 + + +## 前提条件 + +在开始之前,请确定以下哪种情况最符合您的需求: + +- 您正在添加一个需要特定数量和类型参数的新方法。 + - 请前往[✅使用FES添加参数验证](#-使用fes添加参数验证)。 +- 您的方法涉及加载特定类型的文件,并且您需要捕获特定于加载文件的错误。 + - 请前往[📥使用FES添加文件加载错误](#-使用fes处理文件加载错误消息)。 +- 您已编写代码检测错误何时发生,并希望显示友好错误。 + - 请前往[🐈使用FES添加库错误信息](#-使用fes添加库错误信息)。 + + + +## ✅ 使用FES添加参数验证 + +### 第1步 – 再次检查您的内联文档 + +首先,确保您的方法有[内联文档](./contributing_to_the_p5js_reference.md),其中包含完整的参数列表。 + +例如,`circle()`方法有以下内联文档,以方法描述开始,后面是参数列表,然后是示例代码: + +``` +/** + * 在画布上绘制一个圆。圆是一个圆形形状。 + * 圆边缘上的每个点到其中心的距离相同。 + * 默认情况下,前两个参数设置圆中心的位置。 + * 第三个参数设置形状的宽度和高度(直径)。 + * 可以使用ellipseMode()函数更改原点。 + * + * @method circle + * @param {Number} x 圆中心的x坐标。 + * @param {Number} y 圆中心的y坐标。 + * @param {Number} d 圆的直径。 + * @chainable + * @example + *
+ * + * circle(30, 30, 20); + * describe('灰色画布中央带有黑色轮廓的白色圆圈。'); + * + *
+ * + */ +``` + +从上面的例子中,FES将查找参数列表以验证参数: + +``` + * @method circle + * @param {Number} x 圆中心的x坐标。 + * @param {Number} y 圆中心的y坐标。 + * @param {Number} d 圆的直径。 +``` + + +### 第2步 – 调用`p5._validateParameters()` + +现在回到您方法的实现,按照以下格式调用`validate_params()`:`p5._validateParameters('[您方法的名称]', arguments);`。 + +例如,以下代码将验证`circle()`的参数并生成FE信息: + +```js +p5._validateParameters('circle', arguments); +``` + +通常在方法中首先调用此函数,以避免在提供的参数不符合预期时继续执行。例如,它在`circle()`方法的第一行被调用: + +```js +p5.prototype.circle = function() { + p5._validateParameters('circle', arguments); + const args = Array.prototype.slice.call(arguments, 0, 2); + args.push(arguments[2]); + args.push(arguments[2]); + return this._renderEllipse(...args); +}; +``` + + +### 第3步 – 构建并测试您的代码以应对典型情况 + +要查看参数验证的效果,请使用`npm run build`重新构建`p5.js`。 + +要测试您的代码,找到`/lib/empty-example/index.html`并将脚本`../p5.min.js`替换为`../p5.js`,如下例所示: + +```js + +``` + +请注意,`lib/p5.min.js`不支持FE信息,因此请使用`lib/p5.js`进行测试。 + +然后,编辑`/lib/empty-example/sketch.js`来测试典型的参数错误情况: + +1. 缺少参数 +2. 参数数量错误 +3. 参数类型错误 + +以下是测试`circle()`方法表达式的示例: + +```js +// 缺少参数 +circle(100); +// 参数数量错误(超过所需数量) +// 注意这段代码仍然能成功绘制一个圆。 +circle(100, 100, 100, 1000); +// 参数类型错误 +circle(100, 100, 'hello'); +``` + +上面的代码应该生成以下FE信息: + +``` +🌸 p5.js says: [sketch.js, line 9] circle()需要至少3个参数,但只收到了1个。 (https://p5js.org/reference/p5/circle) +🌸 p5.js says: [sketch.js, line 14] circle()需要不超过3个参数,但收到了4个。 (https://p5js.org/reference/p5/circle) +🌸 p5.js says: [sketch.js, line 12] circle()的第三个参数需要Number类型,但收到了string类型。 (https://p5js.org/reference/p5/circle) +``` + +恭喜🎈!您现在已经完成了为新方法添加参数验证。 + + +## 📥 使用FES处理文件加载错误消息 + +### 第1步 – 检查文件加载错误情况列表 + +文件加载错误分为多个不同的情况,以便在错误发生时提供尽可能有帮助的信息。这使p5.js能够在不同情况下显示不同的错误。例如,当它无法读取字体文件中的数据时,它会显示一个与尝试加载过大无法读取的文件时不同的错误。 + +这些情况都有自己的编号,可以在`core/friendly_errors/file_errors.js`文件的顶部找到。 + +当您希望添加文件加载错误时,首先查看`core/friendly_errors/file_errors.js`中的`fileLoadErrorCases`,看看是否有适用于您情况的现有案例。 + + + +例如,您可能正在加载基于字符串的文件。这对应于`fileLoadErrorCases`中的`case 3`: + +```js +case 3: + return { + message: translator('fes.fileLoadError.strings', { + suggestion + }), + method: 'loadStrings' + }; +``` + +如果您正在处理的场景已经有相关的编号,请记住案例编号,并跳至[**第4步**](#step-4)。如果您在`fileLoadErrorCases`中找不到匹配的情况,请转到[**第2步**](#step-2)创建新的情况。 + + +### 第2步 – 在问题面板上讨论添加新的错误情况 + +接下来,您将提交一个问题工单,讨论创建新的情况或确认您的情况不是现有情况的重复。编写一个简短的段落描述您的新方法以及用户可能遇到这种特定文件加载错误的场景。然后再写一个简短的段落描述您方法中的错误处理以及它加载的文件类型。 + +转到[问题面板](https://github.com/processing/p5.js/issues),按"New Issue"按钮,然后选择"Issue: 💡 Existing Feature Enhancement"选项。应该出现一个空表单。 + +添加一个标题,如"向`fileLoadErrorCases`添加新情况:\[您的文件加载错误情况的高级描述]"。对于"Increasing access"部分,输入您在此步骤开始时准备的简短段落,描述典型情况。 + +然后,在"Most appropriate sub-area of p5.js?"问题中勾选"Friendly Errors"框。最后,在"Feature enhancement details"部分,输入详细说明错误处理和加载文件类型的段落。 + + +### 第3步 – 向`fileLoadErrorCases`添加新情况 + +在与维护者确认后,您可以向`fileLoadErrorCases`添加新情况。在`fileLoadErrorCases`的`switch`语句中,转到情况列表的末尾,并按照以下格式添加新情况: + +``` +case {{next available case number}}: + return { + message: translator('fes.fileLoadError.{{tag name}}', { + suggestion + }), + method: '{{name of your method}}' + }; +``` + +在上面的例子中,双尖括号(`{{}}`)中的任何内容都是您应该替换的内容。例如,如果前一个情况编号是11,您的代码应该以`case 12:`开始,最终代码中没有双括号。 + + +### 第4步 – 调用`p5._friendlyFileLoadError()` + +添加您的情况后,您现在可以在错误处理语句中调用`p5._friendlyFileLoadError([情况编号], [文件路径])`。 + +例如,请查看`loadStrings()`方法加载基于字符串的文件(对应于`fileLoadErrorCases`中的`case 3`)。`loadStrings()`方法使用[`httpDo.call()`](https://p5js.org/reference/p5/httpDo)和一个在文件错误情况下执行的自定义回调方法: + +```js +p5.prototype.httpDo.call( + this, + args[0], + 'GET', + 'text', + data => { + // [... 省略的代码 ...] + }, + function(err) { + // 错误处理 + p5._friendlyFileLoadError(3, args[0]); + // [... 省略的代码 ...] + } + ); +``` + +我们可以看到错误回调函数如何调用`p5._friendlyFileLoadError(3, [the first argument, which is a file path])`来生成以下FE信息: + +``` +🌸 p5.js says: 看起来加载文本文件时出现了问题。请检查文件路径(assets/wrongname.txt)是否正确,尝试在线托管文件,或运行本地服务器。 ++ 更多信息:https://github.com/processing/p5.js/wiki/Local-server +``` + +恭喜🎈!您现在已经完成为带有文件加载的方法实现FE。 + + + +## 🐈 使用FES添加库错误信息 + +### 第1步 – 编写代码检测错误何时发生 + +首先,查找用户在使用您的方法时可能遇到的典型错误情况,并创建逻辑来捕获这些情况。此外,如果适用,请考虑提供故障保护措施,例如为缺少的参数使用默认值。确定对用户有帮助的FE信息的情况。 + +[MDN Web文档中的这个指南](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling)提供了关于控制流和JavaScript原生错误处理结构的良好概述。 + +\ + + + +### 第2步 – 调用`p5._friendlyError()` + +要生成FE信息,您只需要在错误处理语句中按照以下格式调用`p5._friendlyError('[custom message]', '[method name]');`。将方括号内(包括方括号)的所有内容替换为您自己的值。 + +例如,以下代码将为`bezierVertex()`生成FE信息: + +```js +p5._friendlyError( + '在调用bezierVertex()之前必须先使用vertex()', + 'bezierVertex' +); +``` + +这应该生成以下FE信息: + +``` +🌸 p5.js says: [sketch.js, line 19] 当调用bezierVertex时,p5js库内部发生了一个错误,错误信息为"在调用bezierVertex()之前必须先使用vertex()"。如果没有特别说明,可能是传递给bezierVertex的参数有问题。 (https://p5js.org/reference/p5/bezierVertex) +``` + +恭喜🎈!您现在已经完成了为您的方法添加库错误信息。 + + +## ✏️ 为国际受众编写友好错误信息 + +FES信息编写者应优先降低理解错误信息的障碍,提高调试过程的可访问性。以下是一个例子: + +``` +🌸 p5.js says: [sketch.js, line 7] circle() was expecting at least 3 arguments, but received only 1. (https://p5js.org/reference/p5/circle)  +``` + +如果浏览器设置为`ko-KR`(韩语)区域设置,上述参数验证信息将以韩语显示: + +``` +🌸 p5.js says: [sketch.js, 줄7] 최소 3개의 인수(argument)를 받는 함수 circle()에 인수가 1개만 입력되었습니다. (https://p5js.org/reference/p5/circle) +``` + +[友好错误i18n指南](https://almchung.github.io/p5-fes-i18n-book/)讨论了在跨文化i18n上下文中编写友好错误信息的挑战和最佳实践。以下是该指南的主要观点: + +- 了解您的受众:不要对错误信息的受众做出假设。尝试了解谁在使用我们的库以及他们如何使用它。 +- 保持语言包容性。我们努力使错误信息"友好",这对您意味着什么?寻找语言中可能的偏见和伤害。 +- 尽可能使用简单的句子。考虑将句子分解成更小的块,以最好地利用[i18next的插值功能](https://www.i18next.com/translation-function/interpolation)。 +- 优先考虑跨文化交流,并提供跨语言的良好体验。避免使用比喻手法。 +- 一次只介绍一个技术概念或技术术语。保持技术写作的一致性。尝试链接一个以初学者友好语言编写的外部资源,其中包含大量简短、实用的示例。 + +[友好错误i18n指南](https://almchung.github.io/p5-fes-i18n-book/)是一个公共项目,您可以通过[这个单独的仓库](https://github.com/almchung/p5-fes-i18n-book)为该指南做出贡献。 + + +## 🔍 可选:单元测试 + +请考虑为您的新FE信息添加单元测试,以便尽早发现错误并确保您的代码向用户传递预期的信息。此外,单元测试是确保其他贡献者的新代码不会意外破坏或干扰您的代码功能的好方法。以下是几个关于单元测试的好指南: + +- [单元测试和测试驱动开发](https://archive.p5js.org/learn/tdd.html),作者Andy Timmons +- [贡献者文档:单元测试](./unit_testing.md) + + + +示例: + +```js +suite('validateParameters: multi-format', function() { + test('color(): 可选参数,类型不正确', function() { + assert.validationError(function() { + p5._validateParameters('color', [0, 0, 0, 'A']); + }); + }); +} +``` + + +## 结论 + +在本指南中,我们提供了为多种不同情况添加FE信息的分步说明,包括: + +- 添加参数验证, +- 处理文件加载错误,以及 +- 为方法添加库错误信息。 + +此外,我们很高兴通过2021-2022年进行的FES调查分享我们社区的见解。调查结果以两种格式提供: + +- [21-22 FES调查报告漫画](https://almchung.github.io/p5jsFESsurvey/) +- [21-22 FES调查完整报告](https://observablehq.com/@almchung/p5-fes-21-survey) + +有关FES设计和技术方面的更深入信息,请参阅[FES自述文档](./friendly_error_system.md)。该文档提供了详细的解释和开发说明,对那些寻求更深入了解FES的人有所帮助。