Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: add additional ordered list options #1183

Merged
merged 4 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/lang/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@ export default {
'name': 'Ordered List Indicator End Style',
'description': 'The ending character of an ordered list indicator',
},
'preserve-start': {
'name': 'Preserve Starting Number',
'description': 'Whether to preserve the starting number of an ordered list. This can be used to have an ordered list that has content in between the ordered list items.',
},
},
// paragraph-blank-lines.ts
'paragraph-blank-lines': {
Expand Down Expand Up @@ -894,6 +898,7 @@ export default {
'SILENT': 'silent',
'ascending': 'ascending',
'lazy': 'lazy',
'preserve': 'preserve',
'Nothing': 'Nothing',
'Remove hashtag': 'Remove hashtag',
'Remove whole tag': 'Remove whole tag',
Expand Down
130 changes: 127 additions & 3 deletions src/rules/ordered-list-style.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {IgnoreTypes} from '../utils/ignore-types';
import {Options, RuleType} from '../rules';
import RuleBuilder, {DropdownOptionBuilder, ExampleBuilder, OptionBuilderBase} from './rule-builder';
import RuleBuilder, {BooleanOptionBuilder, DropdownOptionBuilder, ExampleBuilder, OptionBuilderBase} from './rule-builder';
import dedent from 'ts-dedent';
import {OrderListItemEndOfIndicatorStyles, OrderListItemStyles, updateOrderedListItemIndicators} from '../utils/mdast';

class OrderedListStyleOptions implements Options {
numberStyle?: OrderListItemStyles = OrderListItemStyles.Ascending;
listEndStyle?: OrderListItemEndOfIndicatorStyles = OrderListItemEndOfIndicatorStyles.Period;
preserveStart?: boolean;
}

@RuleBuilder.register
Expand All @@ -23,7 +24,7 @@ export default class OrderedListStyle extends RuleBuilder<OrderedListStyleOption
return OrderedListStyleOptions;
}
apply(text: string, options: OrderedListStyleOptions): string {
return updateOrderedListItemIndicators(text, options.numberStyle, options.listEndStyle);
return updateOrderedListItemIndicators(text, options.numberStyle, options.listEndStyle, options.preserveStart);
}
get exampleBuilders(): ExampleBuilder<OrderedListStyleOptions>[] {
return [
Expand Down Expand Up @@ -131,6 +132,119 @@ export default class OrderedListStyle extends RuleBuilder<OrderedListStyleOption
numberStyle: OrderListItemStyles.Lazy,
},
}),
new ExampleBuilder({
description: 'Ordered lists have list items set to ascending numerical order using initial indicator number when Number Style is `ascending` and `preserveStart` is enabled',
before: dedent`
1. Item 1
2. Item 2
4. Item 3
${''}
Some text here
${''}
4. Item 4
5. Item 5
7. Item 6
`,
after: dedent`
1. Item 1
2. Item 2
3. Item 3
${''}
Some text here
${''}
4. Item 4
5. Item 5
6. Item 6
`,
options: {
numberStyle: OrderListItemStyles.Ascending,
preserveStart: true,
},
}),
new ExampleBuilder({
description: 'Nested ordered lists have list items set to ascending numerical order using initial indicator number when Number Style is `ascending` and `preserveStart` is enabled',
before: dedent`
4. Item 4
2. Item 5
2. Subitem 2
5. Subitem 3
2. Subitem 4
4. Item 6
`,
after: dedent`
4. Item 4
5. Item 5
2. Subitem 2
3. Subitem 3
4. Subitem 4
6. Item 6
`,
options: {
preserveStart: true,
},
}),
new ExampleBuilder({
description: 'Ordered lists have list items set to initial indicator number when Number Style is `lazy` and `preserveStart` is enabled',
before: dedent`
2. Item 2
5. Item 3
4. Item 4
`,
after: dedent`
2. Item 2
2. Item 3
2. Item 4
`,
options: {
numberStyle: OrderListItemStyles.Lazy,
preserveStart: true,
},
}),
new ExampleBuilder({
description: 'Nested ordered lists have list items set to initial indicator number when Number Style is `lazy` and `preserveStart` is enabled',
before: dedent`
4. Item 4
2. Item 5
2. Subitem 2
5. Subitem 3
2. Subitem 4
4. Item 6
`,
after: dedent`
4. Item 4
4. Item 5
2. Subitem 2
2. Subitem 3
2. Subitem 4
4. Item 6
`,
options: {
numberStyle: OrderListItemStyles.Lazy,
preserveStart: true,
},
}),
new ExampleBuilder({
description: 'Ordered lists items are not modified when Number Style is `preserve`',
before: dedent`
4. Item 4
2. Item 5
2. Subitem 2
5. Subitem 3
2. Subitem 4
4. Item 6
`,
after: dedent`
4. Item 4
2. Item 5
2. Subitem 2
5. Subitem 3
2. Subitem 4
4. Item 6
`,
options: {
numberStyle: OrderListItemStyles.Preserve,
},
}),
];
}
get optionBuilders(): OptionBuilderBase<OrderedListStyleOptions>[] {
Expand All @@ -147,7 +261,11 @@ export default class OrderedListStyle extends RuleBuilder<OrderedListStyleOption
},
{
value: OrderListItemStyles.Lazy,
description: 'Makes sure ordered list item indicators all are the number 1',
description: 'Makes sure ordered list item indicators all are the same',
},
{
value: OrderListItemStyles.Preserve,
description: 'Preserves ordered list item indicators as they are',
},
],
}),
Expand All @@ -167,6 +285,12 @@ export default class OrderedListStyle extends RuleBuilder<OrderedListStyleOption
},
],
}),
new BooleanOptionBuilder<OrderedListStyleOptions>({
OptionsClass: OrderedListStyleOptions,
nameKey: 'rules.ordered-list-style.preserve-start.name',
descriptionKey: 'rules.ordered-list-style.preserve-start.description',
optionsKey: 'preserveStart',
}),
];
}
}
10 changes: 6 additions & 4 deletions src/utils/mdast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export enum MDAstTypes {
export enum OrderListItemStyles {
Ascending = 'ascending',
Lazy = 'lazy',
Preserve = 'preserve',
}

export enum OrderListItemEndOfIndicatorStyles {
Expand Down Expand Up @@ -670,7 +671,7 @@ export function ensureEmptyLinesAroundHorizontalRule(text: string): string {
return text;
}

export function updateOrderedListItemIndicators(text: string, orderedListStyle: OrderListItemStyles, orderedListEndStyle: OrderListItemEndOfIndicatorStyles): string {
export function updateOrderedListItemIndicators(text: string, orderedListStyle: OrderListItemStyles, orderedListEndStyle: OrderListItemEndOfIndicatorStyles, preserveStart: boolean): string {
const positions: Position[] = getPositions(MDAstTypes.List, text);
if (!positions) {
return text;
Expand Down Expand Up @@ -704,8 +705,7 @@ export function updateOrderedListItemIndicators(text: string, orderedListStyle:

let lastItemListIndicatorLevel = -1;
listText = listText.replace(/^(( |\t|> )*)((\d+(\.|\)))|[-*+])([^\n]*)$/gm, (listItem: string, $1: string = '', _$2: string, $3: string, _$4: string, _$5: string, $6: string) => {
let listItemIndicatorNumber = 1;

let listItemIndicatorNumber = (orderedListStyle === OrderListItemStyles.Preserve || preserveStart) ? Number(_$4) : 1;
const listItemIndicatorLevel = getListItemLevel($1);
// when dealing with a value that is not an int reset all values greater than or equal to the current list level
if (!/^\d/.test($3)) {
Expand All @@ -719,9 +719,11 @@ export function updateOrderedListItemIndicators(text: string, orderedListStyle:
if (orderedListStyle === OrderListItemStyles.Ascending) {
listItemIndicatorNumber = preListIndicatorLevelsToIndicatorNumber.get(listItemIndicatorLevel) + 1;
preListIndicatorLevelsToIndicatorNumber.set(listItemIndicatorLevel, listItemIndicatorNumber);
} else if (preserveStart) {
listItemIndicatorNumber = preListIndicatorLevelsToIndicatorNumber.get(listItemIndicatorLevel);
}
} else {
preListIndicatorLevelsToIndicatorNumber.set(listItemIndicatorLevel, 1);
preListIndicatorLevelsToIndicatorNumber.set(listItemIndicatorLevel, listItemIndicatorNumber);
}

// if we have removed an indentation level then go ahead and remove the last set of sublist info for any levels between those two levels
Expand Down
Loading