diff --git a/.github/contributing/writing-guide.md b/.github/contributing/writing-guide.md index 44320ee1ab..a686f0924e 100644 --- a/.github/contributing/writing-guide.md +++ b/.github/contributing/writing-guide.md @@ -10,15 +10,15 @@ Writing documentation is an exercise in empathy. We're not describing an objecti - Cognitive capacity is **depleted more slowly** when we help them feel consistently smart, powerful, and curious. Breaking things down into digestible pieces and minding the flow of the document can help keep them in this state. - **Always try to see from the user's perspective.** When we understand something thoroughly, it becomes obvious to us. This is called _the curse of knowledge_. In order to write good documentation, try to remember what you first needed to know when learning this concept. What jargon did you need to learn? What did you misunderstand? What took a long time to really grasp? Good documentation meets users where they are. It can be helpful to practice explaining the concept to people in person before. - **Describe the _problem_ first, then the solution.** Before showing how a feature works, it's important to explain why it exists. Otherwise, users won't have the context to know if this information is important to them (is it a problem they experience?) or what prior knowledge/experience to connect it to. -- **While writing, don't be afraid to ask questions**, _especially_ if you're afraid they might be "dumb". Being vulnerable is hard, but it's the only way for us to more fully understand what we need to explain. -- **Be involved in feature discussions.** The best APIs come from documentation-driven development, where we build features that are easy to explain, rather than trying to figure out how to explain them later. Asking questions (especially "dumb" questions) earlier often helps reveal confusions, inconsistencies, and problematic behavior before a breaking change would be required to fix them. +- **While writing, don't be afraid to ask questions**, _especially_ if you're afraid that your questions might be "foolish". Being vulnerable is hard, but it's the only way for us to more fully understand what we need to explain. +- **Be involved in feature discussions.** The best APIs come from documentation-driven development, where we build features that are easy to explain, rather than trying to figure out how to explain them later. Asking questions (especially "foolish" questions) earlier often helps reveal confusions, inconsistencies, and problematic behavior before a breaking change would be required to fix them. ## Organization - **Installation/Integration**: Provide a thorough overview of how to integrate the software into as many different kinds of projects as necessary. - **Introduction/Getting Started**: - Provide a less than 10 minute overview of the problems the project solves and why it exists. - - Provide a less than 30 minute overview of the problems the project solves and how, including when and why to use the project and some simple code examples. At the end, link to both to Installation page and the beginning of the Essentials Guide. + - Provide a less than 30 minute overview of the problems the project solves and how, including when and why to use the project and some simple code examples. At the end, link to both the Installation page and the beginning of the Essentials Guide. - **Guide**: Make users feel smart, powerful, and curious, then maintain this state so that users maintain the motivation and cognitive capacity to keep learning more. Guide pages are meant to be read sequentially, so should generally be ordered from the highest to lowest power/effort ratio. - **Essentials**: It should take no longer than 5 hours to read the Essentials, though shorter is better. Its goal is to provide the 20% of knowledge that will help users handle 80% of use cases. Essentials can link to more advanced guides and the API, though, in most cases, you should avoid such links. When they are provided, you need also provide a context so users are aware if they should follow this link on their first reading. Otherwise, many users end up exhausting their cognitive capacity link-hopping, trying to fully learn every aspect of a feature before moving on, and as a result, never finish that first read-through of the Essentials. Remember that a smooth read is more important than being thorough. We want to give people the information they need to avoid a frustrating experience, but they can always come back and read further, or Google a less common problem when they encounter it. - **Advanced**: While the Essentials helps people handle ~80% of use cases, subsequent guides help get users to 95% of use cases, plus more detailed information on non-essential features (e.g. transitions, animations), more complex convenience features (e.g. mixins, custom directives), and dev experience improvements (e.g. JSX, plugins). The final 5% of use cases that are more niche, complex, and/or prone to abuse will be left to the cookbook and API reference, which can be linked to from these advanced guides. @@ -59,9 +59,9 @@ Writing documentation is an exercise in empathy. We're not describing an objecti - **When referencing a directly following example, use a colon (`:`) to end a sentence**, rather than a period (`.`). - **Use the Oxford comma** (e.g. "a, b, and c" instead of "a, b and c"). ![Why the Oxford comma is important](./oxford-comma.jpg) - Source: [The Serial (Oxford) Comma: When and Why To Use It](https://www.inkonhand.com/2015/10/the-serial-oxford-comma-when-and-why-to-use-it/) -- **When referencing the name of a project, use the name that project refers to itself as.** For example, "webpack" and "npm" should both use lowercase as that's how their documentation refers to them. +- **When referencing the name of a project, use the name that the project refers to itself as.** For example, "webpack" and "npm" should both use lowercase as that's how their documentation refers to them. - **Use Title Case for headings** - at least for now, since it's what we use through the rest of the docs. There's research suggesting that sentence case (only first word of the heading starts with a capital) is actually superior for legibility and also reduces the cognitive overhead for documentation writers, since they don't have to try to remember whether to capitalize words like "and", "with", and "about". -- **Don't use emojis (except in discussions).** Emojis are cute and friendly, but they can be a distraction in documentation and some emoji even convey different meanings in different cultures. +- **Don't use emojis (except in discussions).** Emojis are cute and friendly, but they can be a distraction in documentation and some emojis even convey different meanings in different cultures. ## Iteration & Communication @@ -85,11 +85,11 @@ Writing documentation is an exercise in empathy. We're not describing an objecti ### Tips, Callouts, Alerts, and Line Highlights -We have some dedicated styles to denote something that's worth highlighting in a particular way. These are captured [on this page](https://vitepress.vuejs.org/guide/markdown.html#custom-containers). **They are to be used sparingly.** +We have some dedicated styles to denote something that's worth highlighting in a particular way. These are captured [on this page](https://vitepress.dev/guide/markdown#custom-containers). **They are to be used sparingly.** -There is a certain temptation to abuse these styles, as one can simply add a change inside a callout. However, this breaks up the flow of reading for the user, and thus, should only be used in special circumstances. Wherever possible, we should attempt to create a narrative and flow within the page to respect the readers cognitive load. +There is a certain temptation to abuse these styles, as one can simply add a change inside a callout. However, this breaks up the flow of reading for the user and should only be used in special circumstances. Wherever possible, we should attempt to create a narrative and flow within the page to respect the reader's cognitive load. -Under no circumstances should 2 alerts be used next to one another, it's a sign that we're not able to explain context well enough. +Under no circumstances should two alerts be used next to one another, it's a sign that we're not able to explain context well enough. ### Contributing diff --git a/.vitepress/config.ts b/.vitepress/config.ts index d83a95b57d..8b3c2e5b96 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -4,7 +4,7 @@ import { defineConfigWithTheme } from 'vitepress' import type { Config as ThemeConfig } from '@vue/theme' import baseConfig from '@vue/theme/config' import { headerPlugin } from './headerMdPlugin' -import { jobsPlugin } from './jobsMdPlugin' +// import { textAdPlugin } from './textAdMdPlugin' const nav: ThemeConfig['nav'] = [ { @@ -16,6 +16,8 @@ const nav: ThemeConfig['nav'] = [ { text: 'Примеры', link: '/examples/' }, { text: 'Быстрый старт', link: '/guide/quick-start' }, // { text: 'Style Guide', link: '/style-guide/' }, + { text: 'Glossary', link: '/glossary/' }, + { text: 'Error Reference', link: '/error-reference/' }, { text: 'Документация для Vue 2', link: 'https://ru.vuejs.org/' @@ -33,7 +35,7 @@ const nav: ThemeConfig['nav'] = [ }, { text: 'Песочница', - link: 'https://sfc.vuejs.org' + link: 'https://play.vuejs.org' }, { text: 'Экосистема', @@ -44,6 +46,11 @@ const nav: ThemeConfig['nav'] = [ items: [ { text: 'Партнёры', link: '/partners/' }, { text: 'Темы', link: '/ecosystem/themes' }, + { text: 'UI компоненты', link: 'https://ui-libs.vercel.app/' }, + { + text: 'Сертификация', + link: 'https://certification.vuejs.org/?ref=vuejs-nav' + }, { text: 'Вакансии', link: 'https://vuejobs.com/?ref=vuejs' }, { text: 'Магазин футболок', link: 'https://vue.threadless.com/' } ] @@ -88,8 +95,8 @@ const nav: ThemeConfig['nav'] = [ items: [ { text: 'Блог', link: 'https://blog.vuejs.org/' }, { text: 'Twitter', link: 'https://twitter.com/vuejs' }, - { text: 'Рассылка', link: 'https://news.vuejs.org/' }, - { text: 'События', link: 'https://events.vuejs.org/' } + { text: 'События', link: 'https://events.vuejs.org/' }, + { text: 'Рассылка', link: '/ecosystem/newsletters' } ] } ] @@ -189,6 +196,7 @@ export const sidebar: ThemeConfig['sidebar'] = { }, { text: 'Входные параметры', link: '/guide/components/props' }, { text: 'События', link: '/guide/components/events' }, + { text: 'Component v-model', link: '/guide/components/v-model' }, { text: 'Передача обычных атрибутов', link: '/guide/components/attrs' @@ -313,16 +321,11 @@ export const sidebar: ThemeConfig['sidebar'] = { { text: 'Техники анимации', link: '/guide/extras/animation' - }, - { - text: 'Трансформация реактивности', - link: '/guide/extras/reactivity-transform' } // { // text: 'Building a Library for Vue', // link: '/guide/extras/building-a-library' // }, - // { text: 'Custom Renderers', link: '/guide/extras/custom-renderer' }, // { // text: 'Vue for React Devs', // link: '/guide/extras/vue-for-react-devs' @@ -416,7 +419,8 @@ export const sidebar: ThemeConfig['sidebar'] = { { text: 'Render-функция', link: '/api/render-function' }, { text: 'Отрисовка на стороне сервера', link: '/api/ssr' }, { text: 'Вспомогательные типы TypeScript', link: '/api/utility-types' }, - { text: 'Пользовательский рендерер', link: '/api/custom-renderer' } + { text: 'Пользовательский рендерер', link: '/api/custom-renderer' }, + { text: 'Compile-Time Flags', link: '/api/compile-time-flags' } ] } ], @@ -595,19 +599,28 @@ export default defineConfigWithTheme({ description: 'Vue.js - Прогрессивный JavaScript-фреймворк', srcDir: 'src', srcExclude: ['tutorial/**/description.md'], - scrollOffset: 'header', head: [ ['meta', { name: 'theme-color', content: '#3c8772' }], - ['meta', { name: 'twitter:site', content: '@vuejs' }], - ['meta', { name: 'twitter:card', content: 'summary' }], + ['meta', { property: 'og:url', content: 'https://vuejs.org/' }], + ['meta', { property: 'og:type', content: 'website' }], + ['meta', { property: 'og:title', content: 'Vue.js' }], + [ + 'meta', + { + property: 'og:description', + content: 'Vue.js - The Progressive JavaScript Framework' + } + ], [ 'meta', { - name: 'twitter:image', + property: 'og:image', content: 'https://vuejs.org/images/logo.png' } ], + ['meta', { name: 'twitter:site', content: '@vuejs' }], + ['meta', { name: 'twitter:card', content: 'summary' }], [ 'link', { @@ -631,6 +644,13 @@ export default defineConfigWithTheme({ // 'data-spa': 'auto', // defer: '' // } + // ], + // [ + // 'script', + // { + // src: 'https://vueschool.io/banner.js?affiliate=vuejs&type=top', + // async: 'true' + // } // ] ], @@ -650,9 +670,39 @@ export default defineConfigWithTheme({ text: '日本語', repo: 'https://github.com/vuejs-translations/docs-ja' }, + { + link: 'https://ua.vuejs.org', + text: 'Українська', + repo: 'https://github.com/vuejs-translations/docs-uk' + }, + { + link: 'https://fr.vuejs.org', + text: 'Français', + repo: 'https://github.com/vuejs-translations/docs-fr' + }, + { + link: 'https://ko.vuejs.org', + text: '한국어', + repo: 'https://github.com/vuejs-translations/docs-ko' + }, + { + link: 'https://pt.vuejs.org', + text: 'Português', + repo: 'https://github.com/vuejs-translations/docs-pt' + }, + { + link: 'https://bn.vuejs.org', + text: 'বাংলা', + repo: 'https://github.com/vuejs-translations/docs-bn' + }, + { + link: 'https://it.vuejs.org', + text: 'Italiano', + repo: 'https://github.com/vuejs-translations/docs-it' + }, { link: '/translations/', - text: 'Переводы', + text: 'Help Us Translate!', isTranslationsDesc: true } ], @@ -692,8 +742,10 @@ export default defineConfigWithTheme({ }, markdown: { + theme: 'github-dark', config(md) { - md.use(headerPlugin).use(jobsPlugin) + md.use(headerPlugin) + // .use(textAdPlugin) } }, @@ -723,9 +775,5 @@ export default defineConfigWithTheme({ json: { stringify: true } - }, - - vue: { - reactivityTransform: true } }) diff --git a/.vitepress/inlined-scripts/restorePreference.js b/.vitepress/inlined-scripts/restorePreference.js index ffff094879..9c06216910 100644 --- a/.vitepress/inlined-scripts/restorePreference.js +++ b/.vitepress/inlined-scripts/restorePreference.js @@ -5,9 +5,9 @@ document.documentElement.classList.add(cls) } } - restore('vue-docs-prefer-composition', 'prefer-composition') + restore('vue-docs-prefer-composition', 'prefer-composition', true) restore('vue-docs-prefer-sfc', 'prefer-sfc', true) - // window.__VUE_BANNER_ID__ = '' + // window.__VUE_BANNER_ID__ = 'herodevs-vue2-nes' // restore(`vue-docs-banner-${__VUE_BANNER_ID__}`, 'banner-dismissed') })() diff --git a/.vitepress/jobsMdPlugin.ts b/.vitepress/textAdMdPlugin.ts similarity index 50% rename from .vitepress/jobsMdPlugin.ts rename to .vitepress/textAdMdPlugin.ts index f72e5f4696..8738c9be7d 100644 --- a/.vitepress/jobsMdPlugin.ts +++ b/.vitepress/textAdMdPlugin.ts @@ -2,17 +2,17 @@ import MarkdownIt from 'markdown-it' const excludedPages = [ 'guide/introduction.md', - 'guide/quick-start.md', - 'guide/essentials/computed.md', - 'guide/essentials/conditional.md', - 'guide/essentials/list.md', - 'guide/essentials/event-handling.md', - 'guide/essentials/forms.md', - 'guide/components/registration.md', - 'guide/components/props.md', - 'guide/components/events.md', - 'guide/components/slots.md', - 'guide/built-ins/teleport.md', + // 'guide/quick-start.md', + // 'guide/essentials/computed.md', + // 'guide/essentials/conditional.md', + // 'guide/essentials/list.md', + // 'guide/essentials/event-handling.md', + // 'guide/essentials/forms.md', + // 'guide/components/registration.md', + // 'guide/components/props.md', + // 'guide/components/events.md', + // 'guide/components/slots.md', + // 'guide/built-ins/teleport.md', 'about/faq.md', 'about/team.md', 'about/releases.md', @@ -22,13 +22,13 @@ const excludedPages = [ 'translations/index.md' ] -export const jobsPlugin = (md: MarkdownIt) => { +export const textAdPlugin = (md: MarkdownIt) => { md.renderer.rules.heading_close = (tokens, i, options, env, self) => { const relativePath = env.relativePath const renderedContent = self.renderToken(tokens, i, options) return excludedPages.includes(relativePath) ? renderedContent - : renderedContent.replace(/<\/h1>/, '') + : renderedContent.replace(/<\/h1>/, '') } } diff --git a/.vitepress/theme/components/Banner.vue b/.vitepress/theme/components/Banner.vue index 088801d7d3..e60de21c8d 100644 --- a/.vitepress/theme/components/Banner.vue +++ b/.vitepress/theme/components/Banner.vue @@ -5,46 +5,401 @@ * 2. uncomment and update BANNER_ID in ../../inlined-scripts/restorePreferences.ts * 3. update --vt-banner-height if necessary */ +import { ref } from 'vue' +import { VTIconPlus } from '@vue/theme' + +const open = ref(true) -let open = $ref(true) /** * Call this if the banner is dismissible */ function dismiss() { - open = false + open.value = false document.documentElement.classList.add('banner-dismissed') localStorage.setItem(`vue-docs-banner-${__VUE_BANNER_ID__}`, 'true') } diff --git a/.vitepress/theme/components/Home.vue b/.vitepress/theme/components/Home.vue index 8f9108b1d3..f419eb19c4 100644 --- a/.vitepress/theme/components/Home.vue +++ b/.vitepress/theme/components/Home.vue @@ -1,6 +1,7 @@ + + + + diff --git a/.vitepress/theme/components/SiteMap.vue b/.vitepress/theme/components/SiteMap.vue new file mode 100644 index 0000000000..47b520c550 --- /dev/null +++ b/.vitepress/theme/components/SiteMap.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/.vitepress/theme/components/SponsorsGroup.vue b/.vitepress/theme/components/SponsorsGroup.vue index ac7433c160..aa32bf6b3a 100644 --- a/.vitepress/theme/components/SponsorsGroup.vue +++ b/.vitepress/theme/components/SponsorsGroup.vue @@ -1,32 +1,66 @@