Skip to content

Commit

Permalink
feat: add position option
Browse files Browse the repository at this point in the history
  • Loading branch information
strdr4605 committed Apr 22, 2020
1 parent 9b0bac9 commit 59e955f
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 20 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Options:
- [maxHeaderLevel](examples/maxHeaderLevel.md)
- [Emoji choice](examples/emojiChoice.md)
- [Start and end](examples/startEnd.md)
- [Change link position](examples/position.md)
## TODO[⬆](#jump2header️⃣)
Expand Down
100 changes: 100 additions & 0 deletions examples/position.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Basic

```bash
jump2header -f examples/position.md --position "start"
```

Some intro text

## Section1

[](#basic)<!-- Link generated with jump2header -->

Section1 is most important section

### Subsection11

[](#basic)<!-- Link generated with jump2header -->

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare dapibus turpis sed egestas. Cras est nunc, pellentesque ac imperdiet aliquet, tristique sed lectus. Quisque lectus lorem, pulvinar non enim nec, aliquam condimentum urna. Morbi porttitor sit amet lectus ut rhoncus. Suspendisse finibus tincidunt justo. Donec consectetur sit amet odio ut molestie. Quisque molestie orci nec tincidunt fermentum. Pellentesque viverra quam ut dolor varius pulvinar. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas enim tortor, commodo lacinia augue sit amet, viverra egestas nibh. Vestibulum leo ex, gravida at mi quis, ultricies pulvinar justo. Aenean ornare leo leo, malesuada suscipit lectus ornare vitae. Duis et ornare neque, id imperdiet augue. Morbi tincidunt erat id pellentesque dignissim. Nullam non sagittis magna. Suspendisse in pellentesque massa.

## Section2 with many words

[](#basic)<!-- Link generated with jump2header -->

Cras vitae diam placerat, interdum augue vel, vehicula magna.

Etiam diam nisl, sagittis vel commodo id, fermentum eu augue.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus venenatis laoreet purus, nec pulvinar mauris faucibus vel. Vivamus non elementum nisl. Sed sit amet mauris urna. Quisque purus mauris, egestas vel pellentesque quis, sollicitudin et urna.

### Subsection21

[](#basic)<!-- Link generated with jump2header -->

Duis fermentum purus a sodales iaculis. Nunc diam turpis, hendrerit ut elit quis, euismod laoreet velit.

Pellentesque laoreet sem id nunc luctus, vitae interdum ipsum commodo. Vivamus semper a magna sollicitudin aliquam.

Mauris a felis nec velit egestas maximus sed et enim. Quisque eget auctor quam, interdum lacinia arcu. Nulla sollicitudin lobortis arcu ultricies scelerisque. Donec faucibus ipsum at libero dictum cursus.
Cras dictum sodales feugiat. Nulla vestibulum metus eu cursus semper.

Phasellus tincidunt varius eleifend. Curabitur fringilla, neque quis ultricies tincidunt, orci ligula blandit sapien, quis iaculis ipsum enim a sapien. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras porta porttitor congue.

Morbi mattis odio at sem rutrum, ut ornare tortor porttitor.

#### Header 4

[](#basic)<!-- Link generated with jump2header -->

Aenean et velit non nisl lobortis tempor. Ut felis augue, luctus quis pellentesque a, aliquet quis eros. Phasellus ut mollis eros. Pellentesque dictum urna eu massa lacinia, vitae ultricies elit facilisis.
Quisque gravida auctor turpis et placerat. Nulla ut pharetra elit, ac tincidunt nulla. Vivamus ullamcorper odio sit amet aliquam porttitor. Pellentesque odio tortor, semper a dictum sed, hendrerit a ligula. Proin convallis felis ac sapien fermentum dignissim. Ut eget nibh ut nulla ullamcorper dignissim molestie id magna.

Pellentesque ac sem eget tellus sagittis lobortis. In convallis suscipit leo et ornare. Sed vel hendrerit neque, non placerat tortor. Aenean placerat tortor orci, ac scelerisque diam consequat a. Suspendisse malesuada viverra mauris sed tincidunt.

## Section3

[](#basic)<!-- Link generated with jump2header -->

Phasellus interdum sapien sed consectetur maximus. Fusce nec condimentum arcu. In aliquet magna lectus, eu pretium erat aliquam sed. Curabitur sodales, ligula eget porta euismod, justo ex sagittis odio, eu elementum velit ex sit amet tellus. Etiam at aliquam ex. Morbi in sodales ligula, nec volutpat lacus. Pellentesque quis aliquet lorem. Morbi vel blandit metus, luctus venenatis massa. Sed a varius ante, at laoreet ipsum.

## Markdown

[](#basic)<!-- Link generated with jump2header -->

### List

[](#basic)<!-- Link generated with jump2header -->

- item 1
- item 2
- subitem21
- item 3

### Links

[](#basic)<!-- Link generated with jump2header -->

[link](https://github.com/strdr4605)
https://github.com/strdr4605

```js
const text = "JavaScript syntax highlighting";
alert(text);
```

### Table

[](#basic)<!-- Link generated with jump2header -->

| Tables | Are | Cool |
| ------------- |:-------------:| -----:|
| col 3 is | right-aligned | $1600 |
| col 2 is | centered | $12 |
| zebra stripes | are neat | $1 |

### Blockquotes

[](#basic)<!-- Link generated with jump2header -->

> Blockquotes are very handy in email to emulate reply text.
> This line is part of the same quote.
38 changes: 25 additions & 13 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { writeFileSync } from "fs";
import yargs from "yargs";
import { CliArgv } from "./interfaces";
import { CliArgv } from "./types";
import { createNewFileContent } from "./transform";
import { getFileContent } from "./utils";

Expand All @@ -11,42 +11,53 @@ const argv: CliArgv = yargs
file: {
alias: "f",
default: "README.md",
describe: "File to be parsed\nNote: file shoud have .md extension",
describe: "File to be parsed\nNote: file shoud have .md extension\n\n",
type: "string",
},
output: {
alias: "o",
describe:
"File to write new content\nNote: input file will be overwritten if not provided",
"File to write new content\nNote: input file will be overwritten if not provided\n\n",
type: "string",
},
slug: {
alias: ["s", "header", "h"],
describe: `Specify header slug to jump to.
Note: use text after "#" in url.
https://github.com/<user>/<repo>#api -> api
`,
https://github.com/<user>/<repo>#api -> api\n\n`,
type: "string",
},
position: {
alias: ["p"],
default: "header",
describe: `Specify position of the link
"header" -> Link will be in header
"start" -> Link will be at the start of the section
"end" -> Link will be at the end of the section
Caution: may be some bugs with "end"\n\n`,
choices: ["header", "start", "end"],
type: "string",
},
start: {
describe: `Specify header from where to start adding links.
Notes:
multiple words should be wrapped in quotes "
will much by RegExp`,
multiple words should be wrapped in quotes ""
will much by RegExp\n\n`,
type: "string",
},
end: {
describe: `Specify header to where to end adding links.
Notes:
multiple words should be wrapped in quotes "
will much by RegExp`,
multiple words should be wrapped in quotes ""
will much by RegExp\n\n`,
type: "string",
},
maxLevel: {
alias: ["l", "max-level"],
default: 6,
describe:
"Specify maximal header level to insert links.\nNote: value between 1 and 6",
"Specify maximal header level to insert links.\nNote: value between 1 and 6\n\n",
choices: [1, 2, 3, 4, 5, 6],
type: "number",
},
Expand All @@ -58,14 +69,14 @@ const argv: CliArgv = yargs
2 -> 🔝
3 -> 🔙
4 -> 🆙
5 -> 🔼`,
5 -> 🔼\n\n`,
choices: [1, 2, 3, 4, 5],
type: "number",
},
silent: {
boolean: true,
describe:
"By default jump2header will add comment to created links.\nUse this flag if you don't want the comment",
"By default jump2header will add comment to created links.\nUse this flag if you don't want the comment\n\n",
type: "boolean",
},
})
Expand All @@ -74,7 +85,8 @@ const argv: CliArgv = yargs
throw new Error('Input file should be markdown format, ".md"');
}
return true;
}).argv;
})
.wrap(85).argv;

const fileContent: string = getFileContent(argv.file);

Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export const MARKDOWN_ANY_LINK_REGEXP = /\[.+\]\(.+\)$/g;
export const MARKDOWN_HEADER_REGEXP = /^(?<headerLevel>\#{1,6})\s+/;
export const MARKDOWN_CODE_BLOCK_REGEXP = /^\`\`\`/;
export const SPICIAL_CHARS_REGEXP = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g;

export const LINK_OFFSET = "\n\n";
51 changes: 44 additions & 7 deletions src/transform.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CliArgv, HeaderType } from "./interfaces";
import { CliArgv, HeaderType } from "./types";
import {
getHeaderLevel,
getSlugFromHeader,
isAnchorLinkInSection,
isAnchorLinkInText,
isCodeBlock,
isHeader,
} from "./utils";
import { EMOJIS, LINK_COMMENT } from "./constants";
import { EMOJIS, LINK_COMMENT, LINK_OFFSET } from "./constants";

export function createNewFileContent(
fileContent: string,
Expand Down Expand Up @@ -59,6 +60,9 @@ export function createNewFileContent(
endHeaderIndex = Infinity;
} else {
endHeaderIndex++; // To include last header when slicing the array.
if ("end" === argv.position) {
endHeaderIndex++;
}
}
} else {
endHeaderIndex = Infinity;
Expand All @@ -69,14 +73,47 @@ export function createNewFileContent(
.filter(
(header) =>
!isAnchorLinkInText(header.text) &&
!isAnchorLinkInSection(
header.index,
argv.position,
fileContentByLine,
) &&
header.level <= argv.maxLevel &&
header.slug !== argv.slug,
)
.forEach((header) => {
fileContentByLine[header.index] += `[${
EMOJIS[argv.emoji - 1]
}](#${anchorSlug})${argv.silent ? "" : LINK_COMMENT}`;
.forEach((header, index) => {
switch (argv.position) {
case "header":
fileContentByLine[header.index] += `[${
EMOJIS[argv.emoji - 1]
}](#${anchorSlug})${argv.silent ? "" : LINK_COMMENT}`;
break;
case "start":
fileContentByLine[header.index] = `${
fileContentByLine[header.index]
}${LINK_OFFSET}[${EMOJIS[argv.emoji - 1]}](#${anchorSlug})${
argv.silent ? "" : LINK_COMMENT
}`;
break;
case "end":
if (0 === index) {
break;
}
fileContentByLine[header.index] = `[${
EMOJIS[argv.emoji - 1]
}](#${anchorSlug})${argv.silent ? "" : LINK_COMMENT}${LINK_OFFSET}${
fileContentByLine[header.index]
}`;
break;
}
});

return fileContentByLine.join("\n");
let newFileContent = fileContentByLine.join("\n");
if (!Number.isFinite(endHeaderIndex) && "end" === argv.position) {
newFileContent += `${LINK_OFFSET}[${
EMOJIS[argv.emoji - 1]
}](#${anchorSlug})\n`;
}

return newFileContent;
}
3 changes: 3 additions & 0 deletions src/interfaces.ts → src/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export type PositionType = "header" | "start" | "end";

export interface CliArgv {
file: string;
output?: string;
slug?: string;
position: PositionType | string;
start?: string;
end?: string;
maxLevel: number;
Expand Down
21 changes: 21 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import emojiRegex from "emoji-regex";
import { readFileSync } from "fs";
import {
LINK_OFFSET,
MARKDOWN_ANCHOR_LINK_REGEXP,
MARKDOWN_ANY_LINK_REGEXP,
MARKDOWN_CODE_BLOCK_REGEXP,
MARKDOWN_HEADER_REGEXP,
SPICIAL_CHARS_REGEXP,
WHITE_SPASE_REGEXP,
} from "./constants";
import { PositionType } from "./types";

export function isHeader(line: string): boolean {
return MARKDOWN_HEADER_REGEXP.test(line);
Expand All @@ -29,6 +31,25 @@ export function isAnchorLinkInText(text: string): boolean {
return MARKDOWN_ANCHOR_LINK_REGEXP.test(text);
}

export function isAnchorLinkInSection(
headerIndex: number,
linkPosition: PositionType | string,
fileContentByLine: string[],
): boolean {
const OFFSET = LINK_OFFSET.length;
return (
{
header: false,
start: MARKDOWN_ANCHOR_LINK_REGEXP.test(
fileContentByLine[headerIndex + OFFSET],
),
end: MARKDOWN_ANCHOR_LINK_REGEXP.test(
fileContentByLine[headerIndex - OFFSET],
),
}[linkPosition as PositionType] || false
);
}

export function getSlugFromHeader(header: string): string {
return header
.trim()
Expand Down

0 comments on commit 59e955f

Please # to comment.