@htmlplus/element 0.4.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/client/decorators/attributes.js +2 -3
  2. package/client/decorators/element.js +15 -18
  3. package/client/decorators/property.js +10 -20
  4. package/client/decorators/state.js +5 -9
  5. package/client/decorators/watch.d.ts +2 -0
  6. package/client/decorators/watch.js +10 -13
  7. package/client/helpers/query.js +3 -3
  8. package/client/helpers/queryAll.js +3 -3
  9. package/client/helpers/slots.js +10 -12
  10. package/client/utils/appendToMethod.d.ts +1 -1
  11. package/client/utils/appendToMethod.js +3 -3
  12. package/client/utils/call.d.ts +1 -1
  13. package/client/utils/call.js +2 -2
  14. package/client/utils/index.d.ts +1 -0
  15. package/client/utils/index.js +1 -0
  16. package/client/utils/request.d.ts +8 -3
  17. package/client/utils/request.js +51 -25
  18. package/client/utils/shadowRoot.d.ts +2 -0
  19. package/client/utils/shadowRoot.js +5 -0
  20. package/client/utils/task.d.ts +4 -4
  21. package/client/utils/task.js +5 -8
  22. package/compiler/compiler.js +21 -20
  23. package/compiler/plugins/assets.d.ts +1 -0
  24. package/compiler/plugins/assets.js +9 -2
  25. package/compiler/plugins/copy.d.ts +3 -4
  26. package/compiler/plugins/copy.js +6 -3
  27. package/compiler/plugins/customElement.js +10 -2
  28. package/compiler/plugins/customElementReact/customElementReact.d.ts +9 -3
  29. package/compiler/plugins/customElementReact/customElementReact.js +9 -42
  30. package/compiler/plugins/customElementReact/templates/src/components/{{fileName}}.compact.ts.hbs +10 -7
  31. package/compiler/plugins/customElementReact/templates/src/components/{{fileName}}.ts.hbs +3 -3
  32. package/compiler/plugins/document.d.ts +2 -1
  33. package/compiler/plugins/document.js +9 -32
  34. package/compiler/plugins/extract.js +2 -4
  35. package/compiler/plugins/index.d.ts +1 -0
  36. package/compiler/plugins/index.js +1 -0
  37. package/compiler/plugins/parse.d.ts +3 -1
  38. package/compiler/plugins/parse.js +8 -7
  39. package/compiler/plugins/readme.d.ts +8 -0
  40. package/compiler/plugins/readme.js +23 -0
  41. package/compiler/plugins/style.d.ts +2 -2
  42. package/compiler/plugins/style.js +8 -5
  43. package/compiler/plugins/webTypes.d.ts +3 -2
  44. package/compiler/plugins/webTypes.js +15 -15
  45. package/compiler/utils/tags.js +21 -32
  46. package/constants/index.d.ts +11 -6
  47. package/constants/index.js +11 -7
  48. package/package.json +1 -1
  49. package/types/context.d.ts +13 -15
@@ -2,12 +2,11 @@ import * as CONSTANTS from '../../constants/index.js';
2
2
  import { appendToMethod, host, syncAttributes } from '../utils/index.js';
3
3
  export function Attributes() {
4
4
  return function (target, propertyKey) {
5
- const symbol = Symbol();
6
5
  appendToMethod(target, CONSTANTS.LIFECYCLE_CONNECTED, function () {
7
- this[symbol] = syncAttributes(host(this));
6
+ this[CONSTANTS.API_ATTRIBUTES_SYNCER] = syncAttributes(host(this));
8
7
  });
9
8
  appendToMethod(target, CONSTANTS.LIFECYCLE_UPDATED, function () {
10
- this[symbol](this[propertyKey]);
9
+ this[CONSTANTS.API_ATTRIBUTES_SYNCER](this[propertyKey]);
11
10
  });
12
11
  };
13
12
  }
@@ -11,10 +11,8 @@ export function Element(tag) {
11
11
  constructor() {
12
12
  super();
13
13
  this.attachShadow({ mode: 'open' });
14
- // TODO
15
14
  this[CONSTANTS.API_INSTANCE] = new constructor();
16
15
  this[CONSTANTS.API_INSTANCE][CONSTANTS.API_HOST] = () => this;
17
- this[CONSTANTS.API_INSTANCE][CONSTANTS.API_STATUS] = 'initialize';
18
16
  }
19
17
  // TODO: ignore functions
20
18
  static get observedAttributes() {
@@ -23,27 +21,26 @@ export function Element(tag) {
23
21
  adoptedCallback() {
24
22
  call(this[CONSTANTS.API_INSTANCE], CONSTANTS.LIFECYCLE_ADOPTED);
25
23
  }
26
- // TODO
27
- attributeChangedCallback(name, prev, next) {
28
- const key = camelCase(name);
29
- const type = getMemberType(this[CONSTANTS.API_INSTANCE], key);
30
- const parsed = parseValue(next, type);
31
- this[CONSTANTS.API_INSTANCE][key] = parsed;
24
+ attributeChangedCallback(attribute, prev, next) {
25
+ const instance = this[CONSTANTS.API_INSTANCE];
26
+ if (instance[CONSTANTS.API_IS_DISABLED_ATTRIBUTE_CHANGED_CALLBACK])
27
+ return;
28
+ const name = camelCase(attribute);
29
+ const type = getMemberType(instance, name);
30
+ const value = parseValue(next, type);
31
+ if (instance[name] === value)
32
+ return;
33
+ instance[name] = value;
32
34
  }
33
35
  connectedCallback() {
34
- this[CONSTANTS.API_INSTANCE][CONSTANTS.API_STATUS] = 'connected';
35
- call(this[CONSTANTS.API_INSTANCE], CONSTANTS.LIFECYCLE_CONNECTED);
36
- request(this[CONSTANTS.API_INSTANCE])
37
- .then(() => {
38
- this[CONSTANTS.API_INSTANCE][CONSTANTS.API_STATUS] = 'loaded';
39
- call(this[CONSTANTS.API_INSTANCE], CONSTANTS.LIFECYCLE_LOADED);
40
- })
41
- .catch((error) => {
42
- throw error;
36
+ const instance = this[CONSTANTS.API_INSTANCE];
37
+ instance[CONSTANTS.API_IS_CONNECTED] = true;
38
+ call(instance, CONSTANTS.LIFECYCLE_CONNECTED);
39
+ request(instance, undefined, undefined, () => {
40
+ call(instance, CONSTANTS.LIFECYCLE_LOADED);
43
41
  });
44
42
  }
45
43
  disconnectedCallback() {
46
- this[CONSTANTS.API_INSTANCE][CONSTANTS.API_STATUS] = 'disconnected';
47
44
  call(this[CONSTANTS.API_INSTANCE], CONSTANTS.LIFECYCLE_DISCONNECTED);
48
45
  }
49
46
  }
@@ -1,33 +1,23 @@
1
- import { paramCase } from 'change-case';
2
1
  import * as CONSTANTS from '../../constants/index.js';
3
- import { defineProperty, getMemberType, host, parseValue, request, updateAttribute, appendToMethod } from '../utils/index.js';
2
+ import { defineProperty, host, request, appendToMethod, updateAttribute } from '../utils/index.js';
4
3
  export function Property(options) {
5
4
  return function (target, propertyKey) {
6
5
  const name = String(propertyKey);
7
- const attribute = paramCase(name);
8
6
  const symbol = Symbol();
9
- const type = getMemberType(target, name);
10
7
  function get() {
11
8
  return this[symbol];
12
9
  }
13
- function set(input) {
14
- const value = this[symbol];
15
- if (input === value)
10
+ function set(next) {
11
+ const previous = this[symbol];
12
+ if (next === previous)
16
13
  return;
17
- this[symbol] = input;
18
- const isReady = this[CONSTANTS.API_STATUS] == 'initialize';
19
- request(this, { [name]: [input, value] }).then(() => {
20
- const element = host(this);
21
- const has = element.hasAttribute(attribute);
22
- if (!isReady && has)
14
+ this[symbol] = next;
15
+ request(this, name, previous, (skip) => {
16
+ if (!(options === null || options === void 0 ? void 0 : options.reflect) || skip)
23
17
  return;
24
- if (!(options === null || options === void 0 ? void 0 : options.reflect))
25
- return;
26
- const raw = element.getAttribute(attribute);
27
- const parsed = parseValue(raw, type);
28
- if (input === parsed)
29
- return;
30
- updateAttribute(element, attribute, input);
18
+ target[CONSTANTS.API_IS_DISABLED_ATTRIBUTE_CHANGED_CALLBACK] = true;
19
+ updateAttribute(host(this), name, next);
20
+ target[CONSTANTS.API_IS_DISABLED_ATTRIBUTE_CHANGED_CALLBACK] = false;
31
21
  });
32
22
  }
33
23
  defineProperty(target, propertyKey, { get, set });
@@ -6,16 +6,12 @@ export function State() {
6
6
  function get() {
7
7
  return this[symbol];
8
8
  }
9
- function set(input) {
10
- const value = this[symbol];
11
- if (input === value)
9
+ function set(next) {
10
+ const previous = this[symbol];
11
+ if (next === previous)
12
12
  return;
13
- this[symbol] = input;
14
- request(this, { [name]: [input, value] })
15
- .then(() => undefined)
16
- .catch((error) => {
17
- throw error;
18
- });
13
+ this[symbol] = next;
14
+ request(this, name, previous);
19
15
  }
20
16
  // TODO: configurable
21
17
  defineProperty(target, propertyKey, { get, set, configurable: true });
@@ -4,5 +4,7 @@ import { PlusElement } from '../../types';
4
4
  * The decorated method will be invoked after any
5
5
  * changes with the key, newValue, and oldValue as parameters.
6
6
  * If the arguments aren't defined, all of the properties and states are considered.
7
+ * @param keys Collection of Property/State names.
8
+ * @param immediate Triggers the callback immediately after initialization.
7
9
  */
8
10
  export declare function Watch(keys?: Array<string>, immediate?: boolean): (target: PlusElement, propertyKey: PropertyKey) => void;
@@ -5,27 +5,24 @@ import { appendToMethod } from '../utils/index.js';
5
5
  * The decorated method will be invoked after any
6
6
  * changes with the key, newValue, and oldValue as parameters.
7
7
  * If the arguments aren't defined, all of the properties and states are considered.
8
+ * @param keys Collection of Property/State names.
9
+ * @param immediate Triggers the callback immediately after initialization.
8
10
  */
9
11
  export function Watch(keys, immediate) {
10
12
  return function (target, propertyKey) {
11
13
  // Registers a lifecycle to detect changes.
12
- appendToMethod(target, CONSTANTS.LIFECYCLE_UPDATED, function ([states]) {
14
+ appendToMethod(target, CONSTANTS.LIFECYCLE_UPDATED, function (states) {
15
+ // Skips the logic if 'immediate' wasn't passed.
16
+ if (!immediate && !this[CONSTANTS.API_IS_LOADED])
17
+ return;
13
18
  // Loops the keys
14
- for (const key of Object.keys(states)) {
19
+ states.forEach((prev, key) => {
15
20
  // TODO
16
21
  if ((keys === null || keys === void 0 ? void 0 : keys.length) && !keys.includes(key))
17
- continue;
18
- // Checks the existence of key
19
- if ((keys === null || keys === void 0 ? void 0 : keys.length) && !(key in states))
20
- continue;
21
- // Gets the current state
22
- const [next, prev] = states[key];
23
- // TODO
24
- if (!immediate && this[CONSTANTS.API_STATUS] != 'loaded')
25
- continue;
22
+ return;
26
23
  // Invokes the method with parameters.
27
- this[propertyKey](next, prev, key);
28
- }
24
+ this[propertyKey](this[key], prev, key);
25
+ });
29
26
  });
30
27
  };
31
28
  }
@@ -1,5 +1,5 @@
1
- import { host } from '../utils/index.js';
1
+ import { shadowRoot } from '../utils/index.js';
2
2
  export function query(target, selectors) {
3
- var _a, _b;
4
- return (_b = (_a = host(target)) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector(selectors);
3
+ var _a;
4
+ return (_a = shadowRoot(target)) === null || _a === void 0 ? void 0 : _a.querySelector(selectors);
5
5
  }
@@ -1,5 +1,5 @@
1
- import { host } from '../utils/index.js';
1
+ import { shadowRoot } from '../utils/index.js';
2
2
  export function queryAll(target, selectors) {
3
- var _a, _b;
4
- return (_b = (_a = host(target)) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelectorAll(selectors);
3
+ var _a;
4
+ return (_a = shadowRoot(target)) === null || _a === void 0 ? void 0 : _a.querySelectorAll(selectors);
5
5
  }
@@ -1,15 +1,13 @@
1
- import { defineProperty } from '../utils/index.js';
2
- import { queryAll } from './queryAll.js';
1
+ import { host } from '../utils/index.js';
3
2
  export const slots = (target) => {
4
3
  var _a;
5
- const result = {};
6
- (_a = queryAll(target, 'slot')) === null || _a === void 0 ? void 0 : _a.forEach((slot) => {
7
- const name = slot.name || 'default';
8
- defineProperty(result, name, {
9
- get() {
10
- return !!slot.assignedNodes().filter((node) => { var _a; return node.nodeName != '#text' || ((_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.trim()); }).length;
11
- }
12
- });
13
- });
14
- return result;
4
+ const slots = {};
5
+ const children = Array.from(host(target).childNodes);
6
+ for (const child of children) {
7
+ const name = child['slot'] || (((_a = child.nodeValue) === null || _a === void 0 ? void 0 : _a.trim()) && 'default');
8
+ if (!name)
9
+ continue;
10
+ slots[name] = true;
11
+ }
12
+ return slots;
15
13
  };
@@ -1 +1 @@
1
- export declare const appendToMethod: (target: any, propertyKey: PropertyKey, handler: (this: any, args: Array<any>) => void) => void;
1
+ export declare const appendToMethod: (target: any, propertyKey: PropertyKey, handler: (this: any, ...parameters: Array<any>) => void) => void;
@@ -1,7 +1,7 @@
1
1
  export const appendToMethod = (target, propertyKey, handler) => {
2
2
  const callback = target[propertyKey];
3
- target[propertyKey] = function () {
4
- handler.bind(this)(Array.from(arguments));
5
- return callback === null || callback === void 0 ? void 0 : callback.bind(this)(arguments);
3
+ target[propertyKey] = function (...parameters) {
4
+ handler.bind(this)(...parameters);
5
+ return callback === null || callback === void 0 ? void 0 : callback.bind(this)(...parameters);
6
6
  };
7
7
  };
@@ -1 +1 @@
1
- export declare const call: (target: any, key: string, ...args: Array<any>) => any;
1
+ export declare const call: (target: any, key: PropertyKey, ...parameters: Array<any>) => any;
@@ -1,4 +1,4 @@
1
- export const call = (target, key, ...args) => {
1
+ export const call = (target, key, ...parameters) => {
2
2
  var _a;
3
- return (_a = target[key]) === null || _a === void 0 ? void 0 : _a.call(target, ...args);
3
+ return (_a = target[key]) === null || _a === void 0 ? void 0 : _a.call(target, ...parameters);
4
4
  };
@@ -13,6 +13,7 @@ export * from './off.js';
13
13
  export * from './on.js';
14
14
  export * from './parseValue.js';
15
15
  export * from './request.js';
16
+ export * from './shadowRoot.js';
16
17
  export * from './syncAttributes.js';
17
18
  export * from './task.js';
18
19
  export * from './toBoolean.js';
@@ -13,6 +13,7 @@ export * from './off.js';
13
13
  export * from './on.js';
14
14
  export * from './parseValue.js';
15
15
  export * from './request.js';
16
+ export * from './shadowRoot.js';
16
17
  export * from './syncAttributes.js';
17
18
  export * from './task.js';
18
19
  export * from './toBoolean.js';
@@ -1,4 +1,9 @@
1
1
  import { PlusElement } from '../../types';
2
- export declare const request: (target: PlusElement, state?: {
3
- [key: string]: [any, any];
4
- } | undefined) => Promise<boolean>;
2
+ /**
3
+ * Updates the DOM with a scheduled task.
4
+ * @param target The component instance.
5
+ * @param name Property/State name.
6
+ * @param previous The previous value of Property/State.
7
+ * @param callback Invoked when the rendering phase is completed.
8
+ */
9
+ export declare const request: (target: PlusElement, name?: string, previous?: any, callback?: Function) => void;
@@ -3,38 +3,64 @@ import { call } from '../utils/call.js';
3
3
  import { task } from '../utils/task.js';
4
4
  import { html, render } from '../vendors/uhtml.js';
5
5
  import { getStyles } from './getStyles.js';
6
- import { host } from './host.js';
7
- const targets = new Map();
8
- export const request = (target, state) => {
9
- let run = targets.get(target);
10
- if (run)
11
- return run(state);
12
- run = task({
13
- canStart: (states, state) => {
14
- // TODO: hasChange
15
- return true;
16
- },
17
- canRun: (states) => {
18
- // TODO: shouldUpdate
19
- return true;
20
- },
21
- run: (states) => {
6
+ import { shadowRoot } from './shadowRoot.js';
7
+ /**
8
+ * Updates the DOM with a scheduled task.
9
+ * @param target The component instance.
10
+ * @param name Property/State name.
11
+ * @param previous The previous value of Property/State.
12
+ * @param callback Invoked when the rendering phase is completed.
13
+ */
14
+ export const request = (target, name, previous, callback) => {
15
+ var _a, _b;
16
+ // Creates/Gets a stacks.
17
+ const stacks = (target[_a = CONSTANTS.API_STACKS] || (target[_a] = new Map()));
18
+ // Creates/Updates a stack
19
+ const stack = stacks.get(name) || { callbacks: [], previous };
20
+ // Adds the callback to the stack, if exists.
21
+ callback && stack.callbacks.push(callback);
22
+ // Stores the stack.
23
+ stacks.set(name, stack);
24
+ // Creates/Gets a micro task function.
25
+ target[_b = CONSTANTS.API_REQUEST] || (target[_b] = task({
26
+ run: () => {
27
+ // Skips the rendering phase if DOM isn't ready.
28
+ if (!target[CONSTANTS.API_IS_CONNECTED])
29
+ return;
30
+ // Calculates the states to pass into lifecycles' callbacks.
31
+ const states = new Map(Array.from(stacks)
32
+ .filter((stack) => stack[0])
33
+ .map((stack) => [stack[0], stack[1].previous]));
34
+ // Calls the lifecycle's callback before the rendering phase.
22
35
  call(target, CONSTANTS.LIFECYCLE_UPDATE, states);
23
- const element = host(target);
24
- render(element.shadowRoot, () => {
36
+ // Calculates the template.
37
+ const template = () => {
38
+ // Calculates the markup.
25
39
  const markup = call(target, CONSTANTS.METHOD_RENDER);
40
+ // Calculates the styles.
26
41
  const styles = getStyles(target);
27
- if (!styles && !markup)
28
- return html ``;
42
+ // Returns the markup if styles don't exist.
29
43
  if (!styles)
30
44
  return markup;
31
- if (!markup)
32
- return html `<style>${styles}</style>`;
45
+ // Returns the markup and styles together.
33
46
  return html `<style>${styles}</style>${markup}`;
47
+ };
48
+ // Renders template to the DOM.
49
+ render(shadowRoot(target), template);
50
+ // Invokes requests' callback.
51
+ stacks.forEach((state) => {
52
+ state.callbacks.forEach((callback, index, callbacks) => {
53
+ callback(callbacks.length - 1 != index);
54
+ });
34
55
  });
56
+ // Calls the lifecycle's callback after the rendering phase.
35
57
  call(target, CONSTANTS.LIFECYCLE_UPDATED, states);
58
+ // TODO: releated to the @Watch decorator.
59
+ target[CONSTANTS.API_IS_LOADED] = true;
60
+ // Clears stacks.
61
+ stacks.clear();
36
62
  }
37
- });
38
- targets.set(target, run);
39
- return run(state);
63
+ }));
64
+ // Calls the micro task.
65
+ call(target, CONSTANTS.API_REQUEST);
40
66
  };
@@ -0,0 +1,2 @@
1
+ import { PlusElement } from '../../types';
2
+ export declare const shadowRoot: (target: PlusElement) => ShadowRoot | null;
@@ -0,0 +1,5 @@
1
+ import { host } from './host.js';
2
+ export const shadowRoot = (target) => {
3
+ var _a;
4
+ return (_a = host(target)) === null || _a === void 0 ? void 0 : _a.shadowRoot;
5
+ };
@@ -1,6 +1,6 @@
1
1
  export interface QueueOptions {
2
- canStart?: (states: any, state: any) => boolean;
3
- canRun?: (states: any) => boolean;
4
- run: (states: any) => void;
2
+ canStart?: () => boolean;
3
+ canRun?: () => boolean;
4
+ run: () => void;
5
5
  }
6
- export declare const task: (options: QueueOptions) => (state?: any) => Promise<boolean>;
6
+ export declare const task: (options: QueueOptions) => () => Promise<boolean>;
@@ -1,10 +1,8 @@
1
1
  export const task = (options) => {
2
- let isPending, states, updatePromise;
3
- const run = (state) => {
4
- const newStates = Object.assign({}, states, state);
5
- if (options.canStart && !options.canStart(newStates, state))
2
+ let isPending, updatePromise;
3
+ const run = () => {
4
+ if (options.canStart && !options.canStart())
6
5
  return Promise.resolve(false);
7
- states = newStates;
8
6
  if (!isPending)
9
7
  updatePromise = enqueue();
10
8
  return updatePromise;
@@ -21,10 +19,9 @@ export const task = (options) => {
21
19
  if (!isPending)
22
20
  return updatePromise;
23
21
  try {
24
- if (options.canRun && !options.canRun(states))
22
+ if (options.canRun && !options.canRun())
25
23
  return (isPending = false);
26
- options.run(states);
27
- states = undefined;
24
+ options.run();
28
25
  isPending = false;
29
26
  return true;
30
27
  }
@@ -1,22 +1,28 @@
1
1
  import ora from 'ora';
2
+ import path from 'path';
2
3
  const logger = ora({
3
4
  color: 'yellow'
4
5
  });
6
+ const log = (message, persist) => {
7
+ var _a, _b;
8
+ (_b = (_a = logger.start(`${new Date().toLocaleTimeString()} [HTMLPLUS] ${message}`))[persist ? 'succeed' : '']) === null || _b === void 0 ? void 0 : _b.call(_a);
9
+ };
5
10
  export default (...plugins) => {
6
11
  let global = {
7
12
  contexts: []
8
13
  };
9
- logger.start(`${plugins.length} Plugins found.`).succeed();
14
+ log(`Starting...`, true);
15
+ log(`${plugins.length} plugins found.`, true);
10
16
  const start = async () => {
11
- logger.start('Starting...').succeed();
17
+ log(`Plugins are starting...`, true);
12
18
  for (const plugin of plugins) {
13
19
  if (!plugin.start)
14
20
  continue;
15
- logger.start(`Plugin '${plugin.name}' starting...`);
21
+ log(`Plugin '${plugin.name}' is starting...`);
16
22
  await plugin.start(global);
17
- logger.start(`Plugin '${plugin.name}' started successfully.`);
23
+ log(`Plugin '${plugin.name}' started successfully.`);
18
24
  }
19
- logger.start(`Plugins started successfully.`).succeed();
25
+ log(`Plugins started successfully.`, true);
20
26
  };
21
27
  const next = async (filePath) => {
22
28
  var _a;
@@ -24,15 +30,11 @@ export default (...plugins) => {
24
30
  let context = {
25
31
  filePath
26
32
  };
27
- let timeout;
28
33
  for (const plugin of plugins) {
29
34
  if (!plugin.next)
30
35
  continue;
31
- clearTimeout(timeout);
32
- logger.start(`Plugin '${plugin.name}' executing...`);
36
+ log(`Plugin '${plugin.name}' is executing on '${path.basename(filePath)}' file.`);
33
37
  const output = await plugin.next(context, global);
34
- logger.start(`Plugin '${plugin.name}' executed successfully.`);
35
- timeout = setTimeout(() => logger.stop(), 1500);
36
38
  // TODO
37
39
  if (output) {
38
40
  context.outputs = ((_a = context.outputs) !== null && _a !== void 0 ? _a : [])
@@ -49,27 +51,26 @@ export default (...plugins) => {
49
51
  });
50
52
  }
51
53
  global.contexts = global.contexts.filter((current) => current.filePath != context.filePath).concat(context);
54
+ log(`Plugin '${plugin.name}' executed successfully on '${path.basename(filePath)}' file.`);
52
55
  if (context.isInvalid)
53
56
  break;
54
57
  }
58
+ logger.stop();
55
59
  if (context.isInvalid)
56
- logger.start(`File '${key}' break executing because file is invalid.`).succeed();
60
+ log(`File '${key}' break executing because file is invalid.`, true);
57
61
  return context;
58
62
  };
59
63
  const finish = async () => {
60
- logger.start('Finishing...').succeed();
64
+ log(`Plugins are finishing...`, true);
61
65
  for (const plugin of plugins) {
62
66
  if (!plugin.finish)
63
67
  continue;
64
- logger.start(`Plugin '${plugin.name}' finishing...`);
68
+ log(`Plugin '${plugin.name}' is finishing...`);
65
69
  await plugin.finish(global);
66
- logger.start(`Plugin '${plugin.name}' finished successfully.`);
70
+ log(`Plugin '${plugin.name}' finished successfully.`);
67
71
  }
68
- logger.start(`Plugins finished successfully.`).succeed();
69
- };
70
- return {
71
- start,
72
- next,
73
- finish
72
+ log(`Plugins finished successfully.`, true);
73
+ log(`Finished.`, true);
74
74
  };
75
+ return { start, next, finish };
75
76
  };
@@ -1,5 +1,6 @@
1
1
  import { Context } from '../../types';
2
2
  export declare type AssetsOptions = {
3
+ once?: boolean;
3
4
  destination: (context: Context) => string;
4
5
  source?: (context: Context) => string;
5
6
  };
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  const defaults = {
4
+ once: true,
4
5
  destination(context) {
5
6
  return `assets/${context.fileName}`;
6
7
  },
@@ -11,14 +12,20 @@ const defaults = {
11
12
  export const assets = (options) => {
12
13
  const name = 'assets';
13
14
  options = Object.assign({}, defaults, options);
15
+ const sources = new Set();
14
16
  const next = (context) => {
15
17
  var _a, _b;
16
- const destination = (_a = options.destination) === null || _a === void 0 ? void 0 : _a.call(options, context);
17
- const source = (_b = options.source) === null || _b === void 0 ? void 0 : _b.call(options, context);
18
+ const source = (_a = options.source) === null || _a === void 0 ? void 0 : _a.call(options, context);
18
19
  if (!source)
19
20
  return;
20
21
  if (!fs.existsSync(source))
21
22
  return;
23
+ if (options.once) {
24
+ if (sources.has(source))
25
+ return;
26
+ sources.add(source);
27
+ }
28
+ const destination = (_b = options.destination) === null || _b === void 0 ? void 0 : _b.call(options, context);
22
29
  fs.copySync(source, destination);
23
30
  context.assets = source;
24
31
  };
@@ -1,13 +1,12 @@
1
1
  export interface CopyOptions {
2
- at?: 'finish' | 'start';
2
+ at?: 'start' | 'next' | 'finish';
3
3
  destination: string;
4
4
  source: string;
5
- transformer?: (parameters: {
6
- content: string;
7
- }) => string;
5
+ transformer?: (content: string) => string;
8
6
  }
9
7
  export declare const copy: (options: CopyOptions) => {
10
8
  name: string;
11
9
  start: () => void;
10
+ next: () => void;
12
11
  finish: () => void;
13
12
  };
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  const defaults = {
4
- at: 'finish',
4
+ at: 'start'
5
5
  };
6
6
  export const copy = (options) => {
7
7
  const name = 'copy';
@@ -12,15 +12,18 @@ export const copy = (options) => {
12
12
  let content;
13
13
  content = fs.readFileSync(options.source, 'utf8');
14
14
  if (options.transformer)
15
- content = options.transformer({ content });
15
+ content = options.transformer(content);
16
16
  fs.ensureDirSync(path.dirname(options.destination));
17
17
  fs.writeFileSync(options.destination, content, 'utf8');
18
18
  };
19
19
  const start = () => {
20
20
  copy('start');
21
21
  };
22
+ const next = () => {
23
+ copy('next');
24
+ };
22
25
  const finish = () => {
23
26
  copy('finish');
24
27
  };
25
- return { name, start, finish };
28
+ return { name, start, next, finish };
26
29
  };