Skip to content

Commit af63336

Browse files
committed
Fixes contribution docs inconsistencies
1 parent e0616e6 commit af63336

File tree

5 files changed

+42
-33
lines changed

5 files changed

+42
-33
lines changed

docs/docs/contribute/contributing-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Typos are embarrassing! Most PRs that fix typos will be accepted immediately. To
2929
- **DO** keep discussions focused. When a new or related topic comes up, it's often better to create a new issue than to side-track the conversation.
3030
- **DO NOT** submit PRs for coding style changes. These changes can cause unnecessary conflicts and make the review process more complicated.
3131
- **DO NOT** surprise us with big PRs. Instead, file an issue and start a discussion so we can agree on a direction before you invest a large amount of time.
32-
- **DO NOT** commit code you didn't write. We encourage you to contribute your own work to maintain
32+
- **DO NOT** commit code you didn't write. We encourage you to contribute your own work to maintain project quality and integrity.
3333

3434
## Contribution paths
3535

docs/docs/contribute/expect-during-pr.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This article aims to provide an understanding of how we review pull requests, wh
1010

1111
Once you submit a PR, one of our maintainers will examine it and check if the PR build has passed. The automated checks include:
1212

13+
- Successful docs build
1314
- Successful code build
1415
- Passing automated tests with 100% coverage
1516
- Absence of issues caught by our linter (ensuring adherence to naming conventions and code consistency)

docs/docs/contribute/new-command/build-command-logic.mdx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,21 @@ class SpoGroupGetCommand extends SpoCommand {
4646
export default new SpoGroupGetCommand();
4747
```
4848

49+
Each command in the CLI for Microsoft 365 follows a consistent class naming convention to ensure clarity and maintainability. The command class name is based on the command's name and follows PascalCase. It is composed of the command's hierarchy segments joined together, followed by the suffix Command. For example, for the command `spo group get`, the class name would be `SpoGroupGetCommand`.
50+
51+
:::warning
52+
53+
To prevent an uncontrolled expansion of command names, we maintain a dictionary of approved command words that can be used when defining a command. This dictionary is located in the [`eslint.config.mjs`](https://github.com/pnp/cli-microsoft365/blob/main/eslint.config.mjs) file.
54+
55+
If a desired command name includes a word that isn't in the approved list, that word should be added to the dictionary to allow the automated workflow to pass successfully.
56+
57+
:::
58+
4959
Depending on your command and the service for which you're building the command, there might be a base class that you can use to simplify the implementation. For example, for SPO, you can inherit from the [SpoCommand](https://github.com/pnp/cli-microsoft365/blob/main/src/m365/base/SpoCommand.ts) base class. This class contains several helper methods to simplify your implementation.
5060

5161
### Include command name
5262

53-
When you create the minimum file, you'll get an error about a nonexistent type within `commands`. This is correct because we haven't defined the name of the command yet. Let's add this to the `commands` export located in `src/m365/spo/commands.ts`:
63+
When you create the minimum file, you'll get an error about a nonexistent type within `commands`. This is correct because we haven't defined the name of the command yet. Let's add this to the `commands` export located in `src/m365/spo/commands.ts`. Note that all commands in this file are sorted strictly **alphabetically**.
5464

5565
```ts title="src/m365/spo/commands.ts"
5666
const prefix: string = 'spo';
@@ -232,7 +242,7 @@ enum AssociatedGroup {
232242
export const options = globalOptionsZod
233243
.extend({
234244
webUrl: zod.alias('u', z.string().refine(url => validation.isValidSharePointUrl(url) === true, url => ({
235-
message: `Specified URL ${url} is not a valid SharePoint URL`,
245+
message: `Specified URL '${url}' is not a valid SharePoint URL.`,
236246
}))),
237247
id: zod.alias('i', z.number().optional()),
238248
name: z.string().optional(),
@@ -254,14 +264,14 @@ class SpoGroupGetCommand extends SpoCommand {
254264

255265
public getRefinedSchema(schema: typeof options): z.ZodEffects<any> | undefined {
256266
return schema
257-
.refine(options => options.id !== undefined || options.name !== undefined && !(options.id !== undefined && options.name !== undefined), {
267+
.refine(options => [options.id, options.name].filter(x => x !== undefined).length === 1, {
258268
message: `Either id or name is required, but not both.`
259269
});
260270
}
261271

262272
public async commandAction(logger: Logger, args: CommandArgs): Promise<void> {
263273
if (this.verbose) {
264-
await logger.logToStderr(`Retrieving information for group in site at ${args.options.webUrl}...`);
274+
await logger.logToStderr(`Retrieving information for group in site at '${args.options.webUrl}'...`);
265275
}
266276

267277
// Command implementation goes here
@@ -317,4 +327,4 @@ If this command fails, be sure to check if your environment has been set up corr
317327

318328
## Next step
319329

320-
Now that the command is fully functional we will need to add some tests to ensure that the command works as expected. This will be explained in the next chapter: [Unit Tests](./unit-tests.mdx).
330+
Now that the command is fully functional we will need to add some tests to ensure that the command works as expected. This will be explained in the next chapter: [Unit Tests](./unit-tests.mdx).

docs/docs/contribute/new-command/unit-tests.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ With the basis of `Mocha` ready, we will set up the basis for `Sinon`. This will
4646

4747
Before we start with the test suite, we want to make sure that the basic functions like `telemetry` and `authentication` are ignored. This will make it so functions like `restoreAuth` return a response when our code, `group-get.ts`, requires it.
4848

49-
```ts title="group-get.spec.ts"
49+
```ts title="src/m365/spo/commands/group/group-get.spec.ts"
5050
// ...
5151
import sinon from 'sinon';
5252
import auth from '../../../../Auth.js';
@@ -221,7 +221,7 @@ describe(commands.GROUP_GET, () => {
221221
};
222222

223223
sinon.stub(request, 'get').callsFake(async opts => {
224-
if (opts.url!.endsWith('/_api/web/AssociatedOwnerGroup')) {
224+
if (opts.url === 'https://contoso.sharepoint.com/sites/Marketing/_api/web/AssociatedOwnerGroup') {
225225
return ownerGroupResponse;
226226
}
227227

@@ -230,6 +230,7 @@ describe(commands.GROUP_GET, () => {
230230

231231
await command.action(logger, {
232232
options: {
233+
webUrl: 'https://contoso.sharepoint.com/sites/Marketing',
233234
associatedGroup: 'Owner'
234235
}
235236
});
@@ -253,10 +254,11 @@ describe(commands.GROUP_GET, () => {
253254
// ...
254255

255256
it('handles errors correctly', async () => {
256-
sinon.stub(request, 'get').rejects({error: { error: { message: 'An error has occured' } } });
257+
sinon.stub(request, 'get').rejects({error: { error: { message: 'An error has occurred' } } });
257258

258259
await assert.rejects(command.action(logger, {
259260
options: {
261+
webUrl: 'https://contoso.sharepoint.com/sites/Marketing',
260262
associatedGroup: 'Visitor'
261263
}
262264
}), new CommandError('An error has occurred'));

docs/docs/contribute/new-command/writing-the-docs.mdx

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ npm start
2828

2929
With our help file created, we can start writing down the command specs. A help file for a command will have at minimum the following topics. The command name as the title, a description, the usage, options, a few examples on how to use them, and a sample response output. We'll start with the `title`, `description`, and `usage`.
3030

31-
````md title="docs\docs\cmd\spo\group\group-get.mdx"
31+
````md title="docs/docs/cmd/spo/group/group-get.mdx"
3232
# spo group get
3333

3434
Gets site group
@@ -44,7 +44,7 @@ m365 spo group get [options]
4444

4545
Most commands will have unique options but every command will make use of our global options. This can be achieved by including `<Global />` under the heading options. This will include the global options in the help page. Before we can use the global options tag, we need to import it from `/docs/cmd/_global.mdx`. This can be done by adding the following import at the top of your help file.
4646

47-
````md title="docs\docs\cmd\spo\group\group-get.mdx"
47+
````md title="docs/docs/cmd/spo/group/group-get.mdx"
4848
import Global from '/docs/cmd/_global.mdx';
4949

5050
<!-- ... -->
@@ -86,7 +86,7 @@ node ./scripts/generate-docs-permissions.mjs
8686

8787
The script above will output the permissions section, you can find an example below.
8888

89-
```md title="docs\docs\cmd\spo\group\group-get.mdx"
89+
```md title="docs/docs/cmd/spo/group/group-get.mdx"
9090
import Tabs from '@theme/Tabs';
9191
import TabItem from '@theme/TabItem';
9292

@@ -116,7 +116,7 @@ import TabItem from '@theme/TabItem';
116116

117117
As they say, a picture is worth a thousand words, same goes for examples of code. This is why we strive to add several examples for each command with some logical option data. This gives more insight to users on how they can implement the command in their script. We require at least 2 examples per command (if possible).
118118

119-
````md title="docs\docs\cmd\spo\group\group-get.mdx"
119+
````md title="docs/docs/cmd/spo/group/group-get.mdx"
120120
## Examples
121121

122122
Get a specific group by its ID
@@ -147,7 +147,7 @@ Some pointers to keep in mind when including sample data in our examples.
147147

148148
We include the response output for each command to give more insight into what users can expect from this command. This is especially useful for commands that return a lot of data. We include the response output in the following formats: JSON, Text, CSV, and Markdown. This is done by using the `Tabs` component from the Docusaurus library. This component allows us to include multiple tabs with different content. The `TabItem` component is used to include the content for each tab. The `value` attribute is used to specify the name of the tab. Make sure to include the `Tabs` and `TabItem` imports at the top of your help file.
149149

150-
````md title="docs\docs\cmd\spo\group\group-get.mdx"
150+
````md title="docs/docs/cmd/spo/group/group-get.mdx"
151151
import Tabs from '@theme/Tabs';
152152
import TabItem from '@theme/TabItem';
153153

@@ -197,7 +197,7 @@ import TabItem from '@theme/TabItem';
197197

198198
```csv
199199
Id,IsHiddenInUI,LoginName,Title,PrincipalType,AllowMembersEditMembership,AllowRequestToJoinLeave,AutoAcceptRequestToJoinLeave,Description,OnlyAllowMembersViewMembership,OwnerTitle,RequestToJoinLeaveEmailSetting
200-
1,,Contoso Visitors,Contoso Visitors,8,,,,Contoso Visitors,,Contoso Owners,
200+
1,0,Contoso Visitors,Contoso Visitors,8,0,0,0,Contoso Visitors,0,Contoso Owners,
201201
```
202202

203203
</TabItem>
@@ -233,30 +233,26 @@ import TabItem from '@theme/TabItem';
233233
Each different verb of command can return a different type of response. This means that a `get` command will return a single object response while a `list` command returns an object list. Below you'll find different examples for different scenarios.
234234

235235
- **A single object response** (planner plan get)
236-
237-
[The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-get/)
238-
[The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-get.mdx?plain=1)
236+
- [The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-get/)
237+
- [The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-get.mdx?plain=1)
239238

240239
- **An object list response** (planner plan list)
240+
- [The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-list/)
241+
- [The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-list.mdx?plain=1)
241242

242-
[The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-list/)
243-
[The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-list.mdx?plain=1)
244-
245-
:::warning
243+
:::warning
246244

247-
Make sure the `Text` output is also in the list format with a single object.
245+
Make sure the `Text` output is also in the list format with a single object.
248246

249-
:::
247+
:::
250248

251249
- **Multiple responses based on the options used** (planner plan add)
252-
253-
[The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-add/)
254-
[The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-add.mdx?plain=1)
250+
- [The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-add/)
251+
- [The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-add.mdx?plain=1)
255252

256253
- **No response** (planner plan remove)
257-
258-
[The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-remove/)
259-
[The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-remove.mdx?plain=1)
254+
- [The docs article](https://pnp.github.io/cli-microsoft365/cmd/planner/plan/plan-remove/)
255+
- [The MarkDown file location](https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/cmd/planner/plan/plan-remove.mdx?plain=1)
260256

261257
Some general pointers to keep in mind when writing the verbose output.
262258

@@ -277,7 +273,7 @@ It is possible that a command needs to include some more information. Some addit
277273

278274
This heading can be used to communicate some important details about your command to the user. This could be to communicate that you used a preview API or that a number option is specified as a 0-based index. Remarks headings are most commonly placed between the headings `Options` and `Examples`.
279275

280-
```md title="graph/schemaextension/schemaextension-list.mdx"
276+
```md title="docs/docs/cmd/graph/schemaextension/schemaextension-list.mdx"
281277
## Remarks
282278

283279
pageNumber is specified as a 0-based index. A value of 2 returns the third page of items.
@@ -287,15 +283,15 @@ pageNumber is specified as a 0-based index. A value of 2 returns the third page
287283

288284
Here we can include some links to the APIs we used in the command or some documentation pages that explain the command usage in more detail. This isn't required but it is nice to have. This heading is most commonly placed at the end of your help page.
289285

290-
```md title="spo/homesite/homesite-get.mdx"
286+
```md title="docs/docs/cmd/spo/homesite/homesite-get.mdx"
291287
## More information
292288

293289
- SharePoint home sites: a landing for your organization on the intelligent intranet: https://techcommunity.microsoft.com/t5/Microsoft-SharePoint-Blog/SharePoint-home-sites-a-landing-for-your-organization-on-the/ba-p/621933
294290
```
295291

296292
## Include into the command navigation
297293

298-
Now that your page is finished, we need to make it available from the command navigation, most commonly found on the left side of the page. To include this, we need to edit the file `sidebars.js` found in the folder `src/config`. Navigate through the section `commands` and locate your commands command group. Here you can add the path to your new help page.
294+
Now that your page is finished, we need to make it available from the command navigation, most commonly found on the left side of the page. To include this, we need to edit the file `sidebars.js` found in the folder `src/config`. Navigate through the section `commands` and locate your commands command group. Here you can add the path to your new help page. Note that all navigation nodes are somewhat sorted alphabetically.
299295

300296
```js title="src/config/sidebars.js"
301297
const sidebars = {

0 commit comments

Comments
 (0)