Skip to content

Commit

Permalink
Merge pull request #23 from nojronatron/staging
Browse files Browse the repository at this point in the history
Pub Pre-release v0.4.0 rc1
  • Loading branch information
nojronatron authored Sep 24, 2024
2 parents d782ce1 + 12e5965 commit 786fb9c
Show file tree
Hide file tree
Showing 15 changed files with 613 additions and 287 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/push-staging-packager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: Staging Packager
on:
push:
branches: ['pub-pre-release']
release:
types:
- created

jobs:
build-test-package:
Expand Down Expand Up @@ -31,8 +34,9 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: markdowntoc-package
path: jr-markdowntoc-vscode-?.?.?.vsix
path: jr-markdowntoc-vscode-0.4.0.vsix
if-no-files-found: 'error'
- name: publish to marketplace
if: success()
run: |
vsce publish -p ${{ secrets.VSCE_PAT}} --pre-release
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"editor.fontFamily": "Consolas, 'Courier New', monospace",
"editor.fontSize": 18,
"editor.lineHeight": 1.4
}
41 changes: 40 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,50 @@
# Change Log

All notable changes to the "markdown-toc" extension will be documented in this file, using Sematic Versioning.
All notable changes to the "markdown-toc" extension will be documented in this file using Sematic Versioning.

See [Keep a Changelog](http://keepachangelog.com/) for how this file is structured.

## [Unreleased]

## [0.4.0] - 2024-09-24

Added:

- Support for Closed ATX Style Headings.

```markdown
# Top Level Heading #

Lorem ipsum...

## Table of Contents ##

- [Second Level Heading](#second-level-heading)

## Second Level Heading ##

Dolor sit amet...

```

Bugfixes:

- Generated Table of Contents should use same style as first discovered heading.
- Comma and period characters cause invalid link fragment generation.
- Slash character in a heading causes invalid link fragment generation.
- Undocumented: Space characters in Heading causes invalid link fragment generation.

## [0.3.1] - 2024-07-22

Added:

- Heading Text used in generatd Table of Contents will only be altered if unsupported characters are included.
- Multiple unit tests for better code coverage.

Bugfixes:

- Table of Contents created invalid link fragments in some cases.

## [0.2.1] - 2024-07-01

Added:
Expand Down
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ Locates all Level 2 headings in the currently selected markdown file and creates

## Features

- Creates a table of contents in the currently open markdown file just prior to the 1st Level 2 heading.
- Creates a table of contents in the currently open markdown file just prior to the first Level 2 heading.
- Links to Level 2 headings are stored in the generated table of contents.
- Supports standard Headings (prefixed with `#`) and alternate Headings syntax (`=` or `-` characters on nextline following heading title).
- Will try to put the generated Table of Contents near the top of the document if there is no Level 1 Heading.
- Attempts to be non-destructive but will strip-out Heading characters that link fragments do not support.
- Uses the VSCode Command Palette to insert the new table of contents.
- Supports standard Headings (Open ATX) that are only prefixed with `#` character(s).
- Support Closed ATX Headings prefixed and suffixed with `#` character(s).
- Supports alternate (Next Line) Headings syntax using `=` or `-` characters on nextline following heading title.
- Generated Table of Contents uses same style of heading (Open, closed, ATX, etc) that it detects within your document.
- If there is no first level heading, the generated Table of Contents will be inserted near the top of the document.
- Unsupported link-fragment characters are removed.
- Headings that contain characters other than alpha-numerics will likely be processed with the exception of unsupported characters such as `<`, `>`, and `:`.
- Use the VSCode Command Palette to insert the new table of contents.

See [CHANGELOG.md](./CHANGELOG.md) for details.

Expand All @@ -35,7 +39,17 @@ Select the command and a Table of Contents will be created with Heading IDs link

## Requirements

The only dependencies are `vscode ^1.90.0 and those listed in devDependencies in the package.json file in my [GitHub Project Repo](https://github.com/nojronatron/markdown-toc/).
Build: `npm install`

Test: `npm test`

Install: Open _Extensions_ panel (`ctrl+shift+x`) in VS Code and search for "Create Markdown TOC".

For development:

- `vscode ^1.90.0`.
- `node 20.14.x`.
- See `package.json` for additional dev dependencies in [my GitHub Project Repo](https://github.com/nojronatron/markdown-toc/).

## Extension Settings

Expand All @@ -48,8 +62,9 @@ ActivationEvents: none.
- Always use a Markdown Linter before running this tool for the best results.
- A Level 1 Heading must be followed by a newline character or it will be ignored (note: Table of Contents generation does not depend on any Level 1 heading specifically).
- Headings that start with a space may cause Create ToC to ignore the heading.
- Headings that contain characters other than alpha-numerics will likely be processed _but_ the generated Table of Contents link might not be active.
- Skipped level 2 headings will not be shown in the generated Table of Contents.
- Using multiple headings types will produce unexpected results.
- A user can create a Heading with many spaces in it that will Lint without error. Create ToC will generate a valid, Linted Link Fragment for that "spacey heading" _but_ the link will be dead.

_Note_: See [GitHub Issues List](https://github.com/nojronatron/markdown-toc/issues) for the most current status.

Expand Down
42 changes: 24 additions & 18 deletions extension-functions/create-toc.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
const { getTitleOnly,
getLoweredKebabCase,
getLinkFragment } = require('./process-headings');

/**
* Generates a table of contents (TOC) based on the captured level 2 headings.
*
* @param {Array<{line, text, isHash}>} capturedL2Headings - An array of captured level 2 headings.
* @returns {string} The generated table of contents.
*/
module.exports = function createTOC(capturedL2Headings) {
let tableOfContentsHeading = 'Table of Contents\n';
let tableOfContentsString = '';
let tableOfContentsHeading = 'Table of Contents';
let tocString = '';
let tocPrefix = '';
let tocSuffix = '';

if (capturedL2Headings[0].isHash) {
tableOfContentsString = `## ${tableOfContentsHeading}\n`;
tocPrefix = `## `;

if (capturedL2Headings[0].isClosedAtx) {
tocSuffix = ` ##`;
}
} else {
tableOfContentsString = `${tableOfContentsHeading}-----------------\n\n`;
tocSuffix = `\n-----------------`;
}


tocString = `${tocPrefix}${tableOfContentsHeading}${tocSuffix}\n\n`;

capturedL2Headings.forEach((item) => {
// Extract the level2 heading text, removing
// characters not allowed in link fragments
const titleOnly = item.text.replaceAll(/(?:[!@$%^&*\(\)\[\]\{\}\:';\.,~`+=\\"\|\/?])/g, '')
.trim();
// Convert the heading text to kebab case
const loweredKebabCase = item.text.toLowerCase()
.replace(/\s/g, '-');
// compose the link fragement title and anchor element
const linkFragment = `- [${titleOnly}](#${loweredKebabCase})\n`;
// append the link fragment to the table of contents string
tableOfContentsString += linkFragment;
// call external modules to do this work
const titleOnly = getTitleOnly(item.text);
const loweredKebabCase = getLoweredKebabCase(titleOnly);
const linkFragment = getLinkFragment(titleOnly, loweredKebabCase);
tocString += linkFragment;
});

// be kind, leave a blank line after the table of contents
tableOfContentsString += '\n';
return tableOfContentsString;
tocString += '\n';
return tocString;
};
20 changes: 16 additions & 4 deletions extension-functions/find-top-heading.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,42 @@
* @property {boolean} isToc - Indicates whether the top heading is a table of contents.
*/
module.exports = function findTopHeading(document) {
const resultObj = { line: -1, text: '', isHash: true, isToc: false };
const resultObj = { line: -1, text: '', isHash: false, isClosedAtx: false, isToc: false };
let lineIdx = 0;
// 1. get index of first newline character
let newlineCharIdx = document.indexOf('\n');
let previousText = '';

// 6. continue until index of newline character is -1
// 2. continue until index of newline character is -1
while (newlineCharIdx > -1) {
// 3. substring from startIdx to index of newline character
let currentText = document.substring(0, newlineCharIdx).trim();

// 4a. if substring starts with '# ' and return with updated resultObj
// 4. check if substring is an open or closed ATX style heading
if (currentText.startsWith('# ')) {
resultObj.line = lineIdx;
resultObj.text = currentText;
resultObj.isHash = true;
resultObj.isClosedAtx = false;
resultObj.isToc = false;

// 4a. if substring starts with '# ' and ends with ' #' return an updated resultObj
if (currentText.endsWith(' #')) {
resultObj.isClosedAtx = true;
}

// 4b. if substring starts with '# ' return an updated resultObj
return resultObj;
}

// 4b. if substring starts with '=' and previous line has text and return with updated resultObj
// 5. if substring starts with '=' and previous line has text return an updated resultObj
if (currentText .startsWith('=')) {
if (previousText.match(/^(?:[a-zA-Z0-9_] *?)+$/m)) {
resultObj.line = lineIdx;
resultObj.text = previousText;
resultObj.isHash = false;
resultObj.isClosedAtx = false;
resultObj.isToc = false;
return resultObj;
}
}
Expand Down
Loading

0 comments on commit 786fb9c

Please sign in to comment.