Add support for precise layout cropping options.
This commit is contained in:
@@ -114,7 +114,8 @@ cameras:
|
||||
|
||||
## `dimensions`
|
||||
|
||||
The `dimensions` block configures the dimensions and layout of media of a given camera.
|
||||
The `dimensions` block configures the dimensions and layout of media of a given camera (see [Card Dimensions](../dimensions.md) to set the dimensions of the whole card and not just a single camera).
|
||||
|
||||
|
||||
```yaml
|
||||
cameras:
|
||||
@@ -130,8 +131,7 @@ cameras:
|
||||
|
||||
### Layout Configuration
|
||||
|
||||
The `layout` block configures the fit and position of the media _within_ the camera dimensions (in order to control the dimensions for the whole card see [the card dimensions configuration](../dimensions.md) ). As the default behavior is to always expand to fit the media precisely, these options only make sense if the camera `dimensions.aspect_ratio` is set to a static value that forces a particular aspect ratio that does not match the camera media.
|
||||
|
||||
The `layout` block configures the fit and position of the media _within_ the camera dimensions (in order to control the dimensions for the whole card see [the card dimensions configuration](../dimensions.md) ).
|
||||
|
||||
```yaml
|
||||
cameras:
|
||||
@@ -143,11 +143,32 @@ cameras:
|
||||
|
||||
| Option | Default | Description |
|
||||
| - | - | - |
|
||||
| `fit` | `contain` | If `contain`, the media is contained within the card and letterboxed if necessary. If `cover`, the media is expanded proportionally (i.e. maintaining the media aspect ratio) until the card is fully covered. If `fill`, the media is stretched to fill the card (i.e. ignoring the media aspect ratio). See [CSS object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) for technical details and a visualization. |
|
||||
| `position` | | A dictionary that contains an `x` and `y` percentage (`0` - `100`) to control the position of the media when the fit is `cover`. This can be effectively used to "pan" the media around. At any given time, only one of `x` and `y` will have an effect, depending on whether media width is larger than the card width (in which case `x` controls the position) or the media height is larger than the card height (in which case `y` controls the position). A value of `0` means maximally to the left or top of the media, a value of `100` means maximally to the right or bottom of the media. See [CSS object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) for technical details and a visualization. |
|
||||
| `fit` | `contain` | If `contain`, the media is contained within the card and letterboxed if necessary. If `cover`, the media is expanded proportionally (i.e. maintaining the media aspect ratio) until the camera/card dimensions are fully covered. If `fill`, the media is stretched to fill the camera/card dimensions (i.e. ignoring the media aspect ratio). See [CSS object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) for technical details and a visualization. |
|
||||
| `position` | | A dictionary that may contain an `x` and `y` percentage (`0` - `100`) to control the position of the media when the fit is `cover` (for other values of `fit` this option has no effect). This can be effectively used to "pan"/cut the media shown. At any given time, only one of `x` and `y` will have an effect, depending on whether media width is larger than the camera/card dimensions (in which case `x` controls the position) or the media height is larger than the camera/card dimensions (in which case `y` controls the position). A value of `0` means maximally to the left or top of the media, a value of `100` means maximally to the right or bottom of the media. See [CSS object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) for technicals. See visualizations below. |
|
||||
| `view_box` | | A dictionary that may contain a `top`, `bottom`, `left` and `right` percentage (`0` - `100`) to precisely crop what part of the media to show by specifying a % inset value from each side. Browsers apply this cropping after `position` and `fit` have been applied. See visualizations below. |
|
||||
|
||||
!> The `view_box` parameter only has effect on browsers that support [`object-view-box`](https://caniuse.com/mdn-css_properties_object-view-box). As of writing this is exclusively Chromium based browsers (e.g. Google Chrome or Microsoft Edge).
|
||||
|
||||
See [media layout examples](../../examples.md?id=media-layout).
|
||||
|
||||
#### Layout **Visualizations**
|
||||
|
||||
##### `fit`
|
||||
|
||||

|
||||
|
||||
##### `position`: When media is shorter than dimensions height
|
||||
|
||||

|
||||
|
||||
##### `position`: When media is thinner than dimensions width
|
||||
|
||||

|
||||
|
||||
#### `view_box`: Precise media cropping
|
||||
|
||||

|
||||
|
||||
## `triggers`
|
||||
|
||||
The `triggers` block configures what triggers a camera. Triggering can be used
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# `dimensions`
|
||||
|
||||
These options control the dimensions and aspect-ratio of the card. These options
|
||||
configuration applies once to the entire card (including the menu, thumbnails,
|
||||
etc), not just to displayed media. This only applies to the card in normal
|
||||
render mode -- when in fullscreen, or when in expanded (popup/dialog mode) the
|
||||
aspect ratio is chosen dynamically to maximize the amount of content shown.
|
||||
These options control the dimensions and aspect-ratio of the card (See [Camera
|
||||
Dimensions](./cameras/README.md?id=dimensions) to set the dimensions of a camera
|
||||
and not the whole card). These options configuration applies once to the entire
|
||||
card (including the menu, thumbnails, etc), not just to displayed media. This
|
||||
only applies to the card in normal render mode -- when in fullscreen, or when in
|
||||
expanded (popup/dialog mode) the aspect ratio is chosen dynamically to maximize
|
||||
the amount of content shown.
|
||||
|
||||
```yaml
|
||||
dimensions:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -35,6 +35,7 @@
|
||||
"lodash-es": "^4.17.21",
|
||||
"masonry-layout": "^4.2.2",
|
||||
"moment": "^2.29.4",
|
||||
"p-queue": "^8.0.1",
|
||||
"propagating-hammerjs": "^2.0.1",
|
||||
"quick-lru": "^6.1.0",
|
||||
"screenfull": "^6.0.2",
|
||||
@@ -89,6 +90,7 @@
|
||||
"build": "yarn run lint && yarn run rollup",
|
||||
"docs": "docsify serve ./docs",
|
||||
"docs-check-links": "find ./docs -name '*.md' -print0 | xargs -0 -n1 markdown-link-check -c ./markdown-link-check.json",
|
||||
"docs-update-images": "./scripts/update-images.sh",
|
||||
"lint": "eslint 'src/**/*.ts'",
|
||||
"rollup": "rollup -c",
|
||||
"prune": "ts-prune",
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
WIDTH=800
|
||||
|
||||
URL_FIT="https://docs.google.com/drawings/d/e/2PACX-1vTq0SVS8HWs3jGC0jjNpJoYfMbZS6P27CYyPlDhSa9OhdB_3jEb0HTLLYwu8Nv3J1TdjAJppcjTiVNy/pub?w=$WIDTH"
|
||||
URL_THINNER_THAN_WIDTH="https://docs.google.com/drawings/d/e/2PACX-1vRkMd89N0tkZt5IghPKhR6gs8zMhB-5_hx5QfP6BCxbsSIga_h44IczP06Sj_YnKkxhe0lRdeR-uh04/pub?w=$WIDTH"
|
||||
URL_SHORTER_THAN_HEIGHT="https://docs.google.com/drawings/d/e/2PACX-1vTKVsXEWIbj9lYKrCeugdLKcK_rOwAZZDK8IzhPdHH4wMwV2v7kEI0nsn2Qgugb00qDVHsE7kE8CBIC/pub?w=$WIDTH"
|
||||
URL_VIEW_BOX="https://docs.google.com/drawings/d/e/2PACX-1vRpPNsaStxW2ENmv1kfUQg41cua9XQ2sQziq2PC8LdRCtkvjHSKYH3CyPO1Pz7kOdiQ2yQKrBX88-TF/pub?w=$WIDTH"
|
||||
|
||||
DIR_MEDIA_LAYOUT_IMAGES="./docs/images/media_layout"
|
||||
|
||||
wget -q -O "$DIR_MEDIA_LAYOUT_IMAGES/fit.png" "$URL_FIT" && \
|
||||
wget -q -O "$DIR_MEDIA_LAYOUT_IMAGES/position-thinner-than-width.png" "$URL_THINNER_THAN_WIDTH" && \
|
||||
wget -q -O "$DIR_MEDIA_LAYOUT_IMAGES/position-shorter-than-height.png" "$URL_SHORTER_THAN_HEIGHT" && \
|
||||
wget -q -O "$DIR_MEDIA_LAYOUT_IMAGES/view-box.png" "$URL_VIEW_BOX"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import add from 'date-fns/add';
|
||||
import cloneDeep from 'lodash-es/cloneDeep';
|
||||
import sum from 'lodash-es/sum';
|
||||
import PQueue from 'p-queue';
|
||||
import { CardCameraAPI } from '../card-controller/types.js';
|
||||
import { CameraConfig, CamerasConfig, PTZAction, PTZPhase } from '../config/types.js';
|
||||
import { MEDIA_CHUNK_SIZE_DEFAULT } from '../const.js';
|
||||
@@ -108,6 +109,7 @@ export class CameraManager {
|
||||
protected _api: CardCameraAPI;
|
||||
protected _engineFactory: CameraManagerEngineFactory;
|
||||
protected _store: CameraManagerStore;
|
||||
protected _initializationLimit = new PQueue({ concurrency: 1 });
|
||||
|
||||
constructor(
|
||||
api: CardCameraAPI,
|
||||
@@ -138,8 +140,6 @@ export class CameraManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
await this.reset();
|
||||
|
||||
// For each camera merge the config (which has no defaults) into the camera
|
||||
// global config (which does have defaults). The merging must happen in this
|
||||
// order, to ensure that the defaults in the cameras global config do not
|
||||
@@ -148,8 +148,16 @@ export class CameraManager {
|
||||
recursivelyMergeObjectsNotArrays({}, cloneDeep(config?.cameras_global), camera),
|
||||
);
|
||||
|
||||
try {
|
||||
const resetAndInitialize = async () => {
|
||||
await this.reset();
|
||||
await this._initializeCameras(cameras);
|
||||
};
|
||||
|
||||
try {
|
||||
// This concurrency limit prevents multiple rapidly arriving configs from
|
||||
// generating reset-n-initialize race conditions (e.g. changing values
|
||||
// rapidly in the config editor).
|
||||
await this._initializationLimit.add(resetAndInitialize);
|
||||
} catch (e: unknown) {
|
||||
this._api.getMessageManager().setErrorIfHigherPriority(e);
|
||||
return false;
|
||||
|
||||
@@ -618,6 +618,14 @@ const mediaLayoutConfigSchema = z.object({
|
||||
y: z.number().min(0).max(100).optional(),
|
||||
})
|
||||
.optional(),
|
||||
view_box: z
|
||||
.object({
|
||||
bottom: z.number().min(0).max(100).optional().default(0),
|
||||
left: z.number().min(0).max(100).optional().default(0),
|
||||
right: z.number().min(0).max(100).optional().default(0),
|
||||
top: z.number().min(0).max(100).optional().default(0),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
export type MediaLayoutConfig = z.infer<typeof mediaLayoutConfigSchema>;
|
||||
|
||||
|
||||
@@ -61,6 +61,14 @@ export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.position.x` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.position.y` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_TOP =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.view_box.top` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_BOTTOM =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.view_box.bottom` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_LEFT =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.view_box.left` as const;
|
||||
export const CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_RIGHT =
|
||||
`${CONF_CAMERAS}.#.dimensions.layout.view_box.right` as const;
|
||||
export const CONF_CAMERAS_ARRAY_TRIGGERS_MOTION =
|
||||
`${CONF_CAMERAS}.#.triggers.motion` as const;
|
||||
export const CONF_CAMERAS_ARRAY_TRIGGERS_OCCUPANCY =
|
||||
|
||||
+68
-1
@@ -46,6 +46,10 @@ import {
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_FIT,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_BOTTOM,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_LEFT,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_RIGHT,
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_TOP,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_CAMERA_NAME,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_CLIENT_ID,
|
||||
CONF_CAMERAS_ARRAY_FRIGATE_LABELS,
|
||||
@@ -1226,6 +1230,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
configPathFit: string,
|
||||
configPathPositionX: string,
|
||||
configPathPositionY: string,
|
||||
configPathPositionTop: string,
|
||||
configPathPositionBottom: string,
|
||||
configPathPositionLeft: string,
|
||||
configPathPositionRight: string,
|
||||
): TemplateResult | void {
|
||||
return this._putInSubmenu(
|
||||
domain,
|
||||
@@ -1236,7 +1244,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
${this._renderOptionSelector(configPathFit, this._layoutFits, {
|
||||
label: localize('config.cameras.dimensions.layout.fit'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionX, {
|
||||
${this._putInSubmenu(
|
||||
`${domain}.position`,
|
||||
true,
|
||||
'config.cameras.dimensions.layout.position.editor_label',
|
||||
{ name: 'mdi:aspect-ratio' },
|
||||
html` ${this._renderNumberInput(configPathPositionX, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.position.x'),
|
||||
@@ -1245,7 +1258,36 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.position.y'),
|
||||
})}`,
|
||||
)}
|
||||
${this._putInSubmenu(
|
||||
`${domain}.view_box`,
|
||||
true,
|
||||
'config.cameras.dimensions.layout.view_box.editor_label',
|
||||
{ name: 'mdi:crop' },
|
||||
html`
|
||||
${this._renderNumberInput(configPathPositionTop, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.view_box.top'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionBottom, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.view_box.bottom'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionLeft, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.view_box.left'),
|
||||
})}
|
||||
${this._renderNumberInput(configPathPositionRight, {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: localize('config.cameras.dimensions.layout.view_box.right'),
|
||||
})}
|
||||
`,
|
||||
)}
|
||||
`,
|
||||
);
|
||||
}
|
||||
@@ -1971,9 +2013,34 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
${this._renderMediaLayout(
|
||||
MENU_CAMERAS_DIMENSIONS_LAYOUT,
|
||||
'config.cameras.dimensions.layout.editor_label',
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_FIT,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_X,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_POSITION_Y,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_TOP,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_BOTTOM,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_LEFT,
|
||||
cameraIndex,
|
||||
),
|
||||
getArrayConfigPath(
|
||||
CONF_CAMERAS_ARRAY_DIMENSIONS_LAYOUT_VIEW_BOX_RIGHT,
|
||||
cameraIndex,
|
||||
),
|
||||
)}
|
||||
`,
|
||||
)}
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "El suport s'estira per omplir la targeta"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "",
|
||||
"x": "Percentatge d'emplaçament horitzontal",
|
||||
"y": "Percentatge d'emplaçament vertical"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "",
|
||||
"editor_label": "",
|
||||
"left": "",
|
||||
"right": "",
|
||||
"top": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "Media is stretched to fill the card"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "Layout Cover Position",
|
||||
"x": "Horizontal placement percentage",
|
||||
"y": "Vertical placement percentage"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "Bottom inset percentage",
|
||||
"editor_label": "Layout View Box",
|
||||
"left": "Left inset percentage",
|
||||
"right": "Right inset percentage",
|
||||
"top": "Top inset percentage"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "Il supporto viene allungato per riempire la scheda"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "",
|
||||
"x": "Percentuale di posizionamento orizzontale",
|
||||
"y": "Percentuale di posizionamento verticale"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "",
|
||||
"editor_label": "",
|
||||
"left": "",
|
||||
"right": "",
|
||||
"top": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "Il supporto viene allungato per riempire la scheda"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "",
|
||||
"x": "Percentuale di posizionamento orizzontale",
|
||||
"y": "Percentuale di posizionamento verticale"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "",
|
||||
"editor_label": "",
|
||||
"left": "",
|
||||
"right": "",
|
||||
"top": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "A mídia é esticada para preencher o cartão"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "",
|
||||
"x": "Porcentagem do posicionamento horizontal",
|
||||
"y": "Porcentagem do posicionamento vertical"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "",
|
||||
"editor_label": "",
|
||||
"left": "",
|
||||
"right": "",
|
||||
"top": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,8 +56,16 @@
|
||||
"fill": "Preencher"
|
||||
},
|
||||
"position": {
|
||||
"editor_label": "",
|
||||
"x": "Percentagem da localização horizontal",
|
||||
"y": "Percentagem da localização vertical"
|
||||
},
|
||||
"view_box": {
|
||||
"bottom": "",
|
||||
"editor_label": "",
|
||||
"left": "",
|
||||
"right": "",
|
||||
"top": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,4 +2,13 @@
|
||||
object-fit: var(--frigate-card-media-layout-fit, contain);
|
||||
object-position: var(--frigate-card-media-layout-position-x, 50%)
|
||||
var(--frigate-card-media-layout-position-y, 50%);
|
||||
|
||||
// This is supported on limited browsers:
|
||||
// See: https://caniuse.com/?search=object-view-box
|
||||
object-view-box: inset(
|
||||
var(--frigate-card-media-layout-view-box-top, 0%)
|
||||
var(--frigate-card-media-layout-view-box-right, 0%)
|
||||
var(--frigate-card-media-layout-view-box-bottom, 0%)
|
||||
var(--frigate-card-media-layout-view-box-left, 0%)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,4 +24,14 @@ export const updateElementStyleFromMediaLayoutConfig = (
|
||||
element.style.removeProperty(`--frigate-card-media-layout-position-${dimension}`);
|
||||
}
|
||||
}
|
||||
for (const dimension of ['top', 'bottom', 'left', 'right']) {
|
||||
if (mediaLayoutConfig?.view_box?.[dimension] !== undefined) {
|
||||
element.style.setProperty(
|
||||
`--frigate-card-media-layout-view-box-${dimension}`,
|
||||
`${mediaLayoutConfig.view_box[dimension]}%`,
|
||||
);
|
||||
} else {
|
||||
element.style.removeProperty(`--frigate-card-media-layout-view-box-${dimension}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3622,6 +3622,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eventemitter3@npm:^5.0.1":
|
||||
version: 5.0.1
|
||||
resolution: "eventemitter3@npm:5.0.1"
|
||||
checksum: 10c0/4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^8.0.1":
|
||||
version: 8.0.1
|
||||
resolution: "execa@npm:8.0.1"
|
||||
@@ -3886,6 +3893,7 @@ __metadata:
|
||||
markdown-link-check: "npm:^3.12.1"
|
||||
masonry-layout: "npm:^4.2.2"
|
||||
moment: "npm:^2.29.4"
|
||||
p-queue: "npm:^8.0.1"
|
||||
prettier: "npm:^2.6.0"
|
||||
propagating-hammerjs: "npm:^2.0.1"
|
||||
quick-lru: "npm:^6.1.0"
|
||||
@@ -6234,6 +6242,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-queue@npm:^8.0.1":
|
||||
version: 8.0.1
|
||||
resolution: "p-queue@npm:8.0.1"
|
||||
dependencies:
|
||||
eventemitter3: "npm:^5.0.1"
|
||||
p-timeout: "npm:^6.1.2"
|
||||
checksum: 10c0/fe185bc8bbd32d17a5f6dba090077b1bb326b008b4ec9b0646c57a32a6984035aa8ece909a6d0de7f6c4640296dc288197f430e7394cdc76a26d862339494616
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-timeout@npm:^3.1.0, p-timeout@npm:^3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "p-timeout@npm:3.2.0"
|
||||
@@ -6243,6 +6261,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-timeout@npm:^6.1.2":
|
||||
version: 6.1.2
|
||||
resolution: "p-timeout@npm:6.1.2"
|
||||
checksum: 10c0/d46b90a9a5fb7c650a5c56dd5cf7102ea9ab6ce998defa2b3d4672789aaec4e2f45b3b0b5a4a3e17a0fb94301ad5dd26da7d8728402e48db2022ad1847594d19
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-try@npm:^2.0.0":
|
||||
version: 2.2.0
|
||||
resolution: "p-try@npm:2.2.0"
|
||||
|
||||
Reference in New Issue
Block a user