@patternplate/client
Version:
Universal javascript client application for patternplate
361 lines (332 loc) • 10.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.selectActiveItem = exports.selectSuggestion = exports.selectDocs = exports.selectLegend = exports.selectPatterns = exports.selectFound = void 0;
var _search = require("@patternplate/search");
var _lodash = require("lodash");
var _reselect = require("reselect");
var _semver = _interopRequireDefault(require("semver"));
var _pool = require("./pool");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const FLAGS = {
alpha: 0,
beta: 1,
rc: 2,
stable: 3,
deprecated: 4
};
const FIELDS = [
/* {
type: "field",
key: "depends",
value: "depends",
description: "patterns depending on id",
operators: ["=", "!=", "^=", "~="]
}, */
{
type: "field",
key: "version",
value: "version",
description: "having version of [value]",
operators: ["=", "!=", ">", ">=", "<", "<=", "^=", "~="]
}, {
type: "field",
key: "flag",
value: "flag",
description: "being flagged as [value]",
operators: ["=", "!=", ">", ">=", "<", "<=", "^=", "~="]
},
/* {
type: "field",
key: "provides",
value: "provides",
description: "patterns providing for id",
operators: ["=", "!=", "^=", "~="]
}, */
{
type: "field",
key: "tags",
value: "tags",
description: "having a tag of [value]",
operators: ["=", "!=", "^=", "~="]
}, {
type: "field",
key: "path",
value: "path",
description: "saved at [value] relative to patternplate.config.js",
operators: ["=", "*="]
}, {
type: "field",
key: "is",
value: "is",
description: "being of type [value]",
operators: ["=", "!="]
}, {
type: "field",
key: "has",
value: "has",
description: "having data of [value]",
operators: ["=", "!="]
}];
const OPERATORS = [{
type: "op",
key: "=",
description: "exact match"
}, {
type: "op",
key: "!=",
description: "negated match"
}, {
type: "op",
key: ">",
description: "greater than"
}, {
type: "op",
key: ">=",
description: "greater than or equal"
}, {
type: "op",
key: "<",
description: "lesser than"
}, {
type: "op",
key: "<=",
description: "lesser than or equal"
}, {
type: "op",
key: "^=",
description: "starts with"
}, {
type: "op",
key: "~=",
description: "contains"
}, {
type: "op",
key: "*=",
description: "matches"
}];
const selectSearch = (0, _reselect.createSelector)(_pool.flat, _search.createSearch);
const selectMatches = (0, _reselect.createSelector)(selectSearch, state => state.search, (search, queryString) => {
if (typeof queryString !== "string" || queryString.length < 3) {
return [];
}
return search(queryString);
});
const selectParsedValue = (0, _reselect.createSelector)(state => state.searchValue, search => _search.Query.parse(search));
const selectLastQuery = (0, _reselect.createSelector)(selectParsedValue, parsed => last(parsed));
function last(query) {
switch (query.type) {
case "string":
return query.value;
case "and":
case "or":
default:
{
const q = query || {};
const values = q.values || [];
const cand = values[values.length - 1];
return cand ? last(cand) : "";
}
}
}
const selectFields = (0, _reselect.createSelector)(selectLastQuery, query => FIELDS.filter(f => f.value.startsWith(query)));
const selectFieldHit = (0, _reselect.createSelector)(state => state.searchValue, selectLastQuery, (value, query) => {
if (query.length === 0) {
return null;
}
return FIELDS.find(f => query.startsWith(f.value));
});
const selectParsedQuery = (0, _reselect.createSelector)(selectLastQuery, query => _search.Term.parse(query));
const selectOps = (0, _reselect.createSelector)(selectParsedQuery, selectFieldHit, (parsed, hit) => {
if (!hit) {
return [];
}
return hit.operators.map(o => OPERATORS.find(op => op.key === o)).filter(o => !parsed.operators || o.key.includes(parsed.operators)).map(o => {
o.value = `${hit.value}${o.key}`;
return o;
});
});
const selectOpsHit = (0, _reselect.createSelector)(selectParsedQuery, selectOps, (query, ops) => {
return ops.find(i => {
if (query.negated) {
return i.key === `!${query.operators}`;
}
return i.key === query.operators;
});
});
const selectFound = (0, _reselect.createSelector)(_pool.flat, selectMatches, (pool, matches) => {
const sorted = (0, _lodash.uniqBy)((0, _lodash.sortBy)(matches.map(match => pool.find(p => p.id === match)), "contentType"), "id");
return sorted.map((s, i) => {
s.index = i;
return s;
});
});
exports.selectFound = selectFound;
const selectPatterns = (0, _reselect.createSelector)(selectFound, found => found.filter(f => f.contentType === "pattern"));
exports.selectPatterns = selectPatterns;
const selectPatternPool = (0, _reselect.createSelector)(_pool.flat, pool => pool.filter(f => f.contentType === "pattern"));
const selectOptions = (0, _reselect.createSelector)(selectPatternPool, selectParsedQuery, selectFieldHit, selectOpsHit, (patterns, parsed, field, op) => {
if (!field || !op) {
return [];
}
switch (field.key) {
case "has":
return [{
type: "quality",
key: "docs",
value: [field.key, op.key, "docs"].join(""),
description: "colocated markdown"
},
/* {
type: "quality",
key: "dependencies",
value: [field.key, op.key, "dependencies"].join(""),
description: "patterns with dependencies"
},
{
type: "quality",
key: "dependents",
value: [field.key, op.key, "dependents"].join(""),
description: "patterns with dependents"
}, */
{
type: "quality",
key: "flag",
value: [field.key, op.key, "flag"].join(""),
description: "flag specified"
}, {
type: "quality",
key: "version",
value: [field.key, op.key, "version"].join(""),
description: "version specified"
}, {
type: "quality",
key: "description",
value: [field.key, op.key, "description"].join(""),
description: "description provided"
}, {
type: "quality",
key: "displayName",
value: [field.key, op.key, "displayName"].join(""),
description: "display name provided"
}, {
type: "quality",
key: "tags",
value: [field.key, op.key, "tags"].join(""),
description: "tag attached"
}];
case "depends":
case "provides":
return patterns.filter(item => item.id.startsWith(parsed.value || "")).map(item => {
return {
type: "pattern",
key: item.id,
value: [field.key, op.key, item.id].join(""),
description: `${item.id}`
};
});
case "tags":
return (0, _lodash.uniq)((0, _lodash.flatten)(patterns.map(item => item.manifest.tags))).filter(Boolean).map(tag => {
return {
type: "tag",
key: tag,
value: [field.key, op.key, tag].join(""),
description: tag
};
});
case "version":
{
const versions = (0, _lodash.uniqBy)(patterns.filter(item => item.manifest.version.startsWith(parsed.value || "")).map(item => item.manifest.version)).filter(version => _semver.default.valid(version)).sort((a, b) => _semver.default.gt(a, b) ? 1 : -1);
return versions.map(v => {
return {
type: "version",
key: v,
value: [field.key, op.key, v].join(""),
description: `${v}`
};
});
}
case "flag":
{
const flags = (0, _lodash.uniqBy)(patterns.filter(item => item.manifest.flag.startsWith(parsed.value || "")).map(item => item.manifest.flag)).filter(flag => typeof flag === "string").sort((a, b) => {
const delta = (FLAGS[a] || 0) - (FLAGS[b] || 0);
return delta === 0 ? a.localeCompare(b) : delta;
});
return flags.map(f => {
return {
type: "flag",
key: f,
value: [field.key, op.key, f].join(""),
description: `${f}`
};
});
}
case "is":
return [{
type: "is",
key: "pattern",
value: [field.key, op.key, "pattern"].join(""),
description: "is a pattern"
}, {
type: "is",
key: "doc",
value: [field.key, op.key, "doc"].join(""),
description: "is a doc"
}];
default:
return [];
}
});
const selectOptionsHit = (0, _reselect.createSelector)(selectParsedQuery, selectOptions, (query, ops) => ops.some(o => o.value === query.raw));
const selectLegend = (0, _reselect.createSelector)(selectParsedValue, selectParsedQuery, selectFields, selectFieldHit, selectOps, selectOpsHit, selectOptions, selectOptionsHit, (parsedValue, parsed, fields, fieldHit, ops, opsHit, options, optionsHit) => {
if (!fieldHit) {
return {
name: "Fields",
items: fields
};
}
if (!opsHit && !parsed.value) {
return {
name: "Operators",
items: ops
};
}
if (!optionsHit && fieldHit && opsHit) {
return {
name: fieldHit.key,
items: options
};
}
return {
name: "",
items: []
};
});
exports.selectLegend = selectLegend;
const selectDocs = (0, _reselect.createSelector)(selectFound, found => found.filter(f => f.contentType === "doc"));
exports.selectDocs = selectDocs;
const selectSuggestion = (0, _reselect.createSelector)(state => state.searchValue, _pool.flat, selectLegend, (search, pool, legend) => {
if (typeof search !== "string" || search.length === 0) {
return "";
}
const match = pool.find(m => [m.id, m.name, (m.manifest || {}).displayName].some(k => k && k.startsWith(search)));
if (match) {
return [match.id, match.name, match.manifest.displayName].find(k => k && k.startsWith(search)) || "";
}
const lmatch = (legend.items || []).find(i => i.value.startsWith(search));
return lmatch ? lmatch.value : null;
});
exports.selectSuggestion = selectSuggestion;
const selectActiveItem = (0, _reselect.createSelector)(state => state, selectFound, state => state.searchPreview, (state, found, preview) => {
const index = Math.min(preview, found.length - 1);
const item = found[index];
return item ? Object.assign({}, item, {
index,
dependents: [],
// rel("dependents"),
dependencies: [] // rel("dependencies")
}) : item;
});
exports.selectActiveItem = selectActiveItem;
//# sourceMappingURL=found.js.map