Skip to content
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
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default [
name: 'merge'
},
{
limit: '2.005 kB',
limit: '2.04 kB',
name: 'all',
path: 'index.js'
}
Expand Down
8 changes: 5 additions & 3 deletions lib/parse/flat-parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ const itemEnhancer = opts => {
}
}

const bookmarksBuilder = ({ add, describe, enhance }) => {
const bookmarksBuilder = ({ add, describe, enhance, transform }) => {
const foldersStack = []
let currFolder

return {
addBookmark: (title, attrs) => {
const bookmark = enhance({ folder: currFolder, title }, attrs)
add(bookmark)
const transformed = transform(bookmark)
transformed && add(transformed)
},
closeFolder: () => {
foldersStack.pop()
Expand All @@ -40,7 +41,8 @@ export const flatParse = (txt, opts = {}) => {
const add = b => bookmarks.push(b)
const describe = d => (bookmarks.at(-1).description = d)
const enhance = itemEnhancer(opts)
const handlers = bookmarksBuilder({ add, describe, enhance })
const transform = opts.transform || (x => x)
const handlers = bookmarksBuilder({ add, describe, enhance, transform })
traverse(txt, handlers)
return bookmarks
}
11 changes: 6 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,11 @@ const bookmarks = flatParse(html)

You can configure the output by activating options passed as the second argument.

| Option | Type | Description |
| -------------- | ---------- | ------------------------------------------------------------------------------------------- |
| `excludeAttrs` | `string[]` | Excludes specified attributes from output. See [attributes definition](./types/attrs.d.ts). |
| `withId` | `boolean` | Adds incremental numeric `id` to items. |
| Option | Type | Description |
| -------------- | --------------------------- | ------------------------------------------ |
| `excludeAttrs` | `string[]` | Excludes specified attributes from output. |
| `withId` | `boolean` | Adds incremental numeric `id` to items. |
| `transform` | `(item: FlatBookmark) => T` | Transforms items, omitting falsy returns. |

### `customParse`

Expand Down Expand Up @@ -183,7 +184,7 @@ const stringified = stringify(parsed)

Converts the flat list from `flatParse` back into an HTML string.

> It requires using `flatParse` with `{ withId: true }` to ensure unique item IDs.
> It requires using `flatParse` with `{ withId: true }` to ensure unique item IDs, and without `transform` to ensure a known structure.

```js
import { flatParse, flatStringify } from 'nbff-parser'
Expand Down
35 changes: 35 additions & 0 deletions test/parse/flat-parse.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,41 @@ describe('flat-parse', () => {
deepEqual(actual, expected)
})

test('with transform', () => {
const initial = `
<DT><H3>JavaScript</H3>
<DL><p>
<DT><A HREF="https://tc39.es/" PERSONAL_TOOLBAR_FOLDER="true">TC39 - Specifying JavaScript.</A>
<DT><H3>Engines</H3>
<DL><p>
<DT><A HREF="https://v8.dev/">V8 JavaScript engine</A>
</DL><p>
</DL><p>
`

const transform = item => {
if (item.personal_toolbar_folder) return

return {
tag: item.folder.map(f => f.title).join(' / '),
title: item.title,
url: item.href
}
}

const actual = flatParse(initial, { transform })

const expected = [
{
tag: 'JavaScript / Engines',
title: 'V8 JavaScript engine',
url: 'https://v8.dev/'
}
]

deepEqual(actual, expected)
})

describe('bookmarks-1.html', () => {
const initial = readFile('./bookmarks-1.html')

Expand Down
24 changes: 23 additions & 1 deletion test/parse/flat-parse.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FlatBookmark, FlatBookmarkWithId } from '../../index.js'
import { FlatBookmark, FlatBookmarkWithId, flatParse } from '../../index.js'

// We check the relevance of types here via `pnpm test:types`.

Expand Down Expand Up @@ -45,3 +45,25 @@ const bookmarkWithId: Required<FlatBookmarkWithId> = {
],
id: 0
}

const parser = flatParse('..')
parser satisfies FlatBookmark[]

const parserWithId = flatParse('..', { withId: true })
parserWithId satisfies FlatBookmark[]
parserWithId satisfies FlatBookmarkWithId[]

const parserWithTransform = flatParse('..', {
transform: item => {
if (!item.href) return
return ({ name: item.title, url: item.href })
}
})
parserWithTransform satisfies { name: string, url: string }[]

const parserWithIdent = flatParse('..', { transform: item => item })
parserWithIdent satisfies FlatBookmark[]

const parserWithIdAndIdent = flatParse('..', { withId: true, transform: item => item })
parserWithIdAndIdent satisfies FlatBookmark[]
parserWithIdAndIdent satisfies FlatBookmarkWithId[]
12 changes: 8 additions & 4 deletions types/parse/flat-parse.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ export type FlatBookmarkWithId = WithId<
}
>

type Truthy<V> = V extends null | undefined | false | 0 | "" ? never : V

// Overload signatures.
export function flatParse(
export function flatParse<T = FlatBookmark>(
text: string,
options?: Partial<{
excludeAttrs: AllAttrKeys[]
withId: false
transform: (item: FlatBookmark) => T
}>
): FlatBookmark[]
export function flatParse(
): Truthy<T>[]
export function flatParse<T = FlatBookmarkWithId>(
text: string,
options: {
excludeAttrs?: AllAttrKeys[]
withId: true
transform?: (item: FlatBookmarkWithId) => T
}
): FlatBookmarkWithId[]
): Truthy<T>[]