Skip to content

Commit

Permalink
feat: add memorization interface
Browse files Browse the repository at this point in the history
  • Loading branch information
fczbkk committed Mar 30, 2021
1 parent 54444be commit 3daac7c
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/memo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
CssSelectors,
CssSelectorsByType,
CssSelectorType,
CssSelectorTypes
} from './types';
import {SELECTOR_TYPE_GETTERS} from './utilities-selectors';

type MemoSelectorData = Map<CssSelectorType, CssSelectors>
type MemoElementData = Map<Element, MemoSelectorData>

/**
* Creates interface for getting CSS selectors by type for an element. Results are remembered for use in later calls.
*/
export function createMemo (memo: MemoElementData = new Map()) {

function getElementData (element: Element): MemoSelectorData {
if (!memo.get(element)) {
memo.set(element, new Map());
}
return memo.get(element);
}

function getSelectorData (element: Element, selectorType: CssSelectorType) {
const elementData = getElementData(element);
if (!elementData.get(selectorType)) {
elementData.set(selectorType, getSelectors(element, selectorType));
}
return elementData.get(selectorType);
}

function getSelectors (element: Element, selectorType: CssSelectorType): CssSelectors {
return SELECTOR_TYPE_GETTERS[selectorType](element);
}

return function (element: Element, selectors: CssSelectorTypes): CssSelectorsByType {
const result = {} as CssSelectorsByType;
selectors.forEach((selectorType) => {
result[selectorType] = getSelectorData(element, selectorType);
});
return result;
};
}
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import {VALID_SELECTOR_TYPES} from './constants'

export type CssSelector = string
export type CssSelectors = Array<CssSelector>

export type CssSelectorMatch = RegExp | string

export type CssSelectorType = typeof VALID_SELECTOR_TYPES[number]
export type CssSelectorTypes = Array<CssSelectorType>

export type CssSelectorsByType = Record<CssSelectorType, CssSelectors>

export type CssSelectorData = {
[key in CssSelectorType]?: Array<string> | Array<Array<string>>
Expand Down
47 changes: 47 additions & 0 deletions test/memo.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {assert} from 'chai'
import {createMemo} from '../src/memo'

describe('memo', () => {

let root

/**
* Simple way to retrieve target element for test.
* @returns {Element}
*/
function getTargetElement () {
return root.querySelector('[data-target]')
}

beforeEach(() => {
root = document.body.appendChild(document.createElement('div'))
})

afterEach(() => {
root.parentNode.removeChild(root)
})

it('should retrieve selectors for an element', () => {
root.innerHTML = '<div data-target></div>'
const element = getTargetElement()
const getElementSelectors = createMemo()
const result = getElementSelectors(element, ['tag'])
assert.deepEqual(result, {tag: ['div']})
})

it('should use remembered value', () => {
root.innerHTML = '<div data-target></div>'
const element = getTargetElement()
const memoData = new Map([
[
element,
new Map([
['tag', ['mock_tag_selector']]
])
]
])
const getElementSelectors = createMemo(memoData)
const result = getElementSelectors(element, ['tag'])
assert.deepEqual(result, {tag: ['mock_tag_selector']})
})
})

0 comments on commit 3daac7c

Please sign in to comment.