Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58c15e414b | |||
| 9b912486fe | |||
| dd4dc06843 | |||
| 4b8f7c7c66 | |||
| e9b5210494 |
@@ -120,6 +120,9 @@
|
||||
"zindex"
|
||||
],
|
||||
"language": "en-US",
|
||||
"files": [
|
||||
"**/*.md"
|
||||
],
|
||||
"ignorePaths": [
|
||||
".cspell.json",
|
||||
"dist/",
|
||||
|
||||
@@ -9,6 +9,8 @@ updates:
|
||||
timezone: Europe/Athens
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
reviewers:
|
||||
- XhmikosR
|
||||
labels:
|
||||
- dependencies
|
||||
- v5
|
||||
|
||||
@@ -31,6 +31,6 @@ jobs:
|
||||
uses: streetsidesoftware/cspell-action@v6
|
||||
with:
|
||||
config: ".cspell.json"
|
||||
files: "**/*.{md,mdx}"
|
||||
files: "**/*.md"
|
||||
inline: error
|
||||
incremental_files_only: false
|
||||
|
||||
@@ -44,3 +44,7 @@ Thumbs.db
|
||||
/site/node_modules
|
||||
/site/.astro
|
||||
/site/public
|
||||
|
||||
# TODO(Astro migration): temporary files and directories during the migration
|
||||
resources/
|
||||
.hugo_build.lock
|
||||
|
||||
+1
-3
@@ -35,9 +35,7 @@ execFile('java', ['-version'], (error, stdout, stderr) => {
|
||||
'Attribute “is:raw” is not serializable as XML 1.0.',
|
||||
'Attribute “is:raw” not allowed on element “code” at this point.',
|
||||
// Astro's expecting trailing slashes on HTML tags such as <br />
|
||||
'Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.',
|
||||
// Allow `switch` attribute.
|
||||
'Attribute “switch” not allowed on element “input” at this point.'
|
||||
'Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.'
|
||||
].join('|')
|
||||
|
||||
const args = [
|
||||
|
||||
@@ -45,7 +45,6 @@ class BaseComponent extends Config {
|
||||
}
|
||||
}
|
||||
|
||||
// Private
|
||||
_queueCallback(callback, element, isAnimated = true) {
|
||||
executeAfterTransition(callback, element, isAnimated)
|
||||
}
|
||||
|
||||
@@ -207,9 +207,6 @@ class Dropdown extends BaseComponent {
|
||||
this._element.setAttribute('aria-expanded', 'false')
|
||||
Manipulator.removeDataAttribute(this._menu, 'popper')
|
||||
EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
|
||||
|
||||
// Explicitly return focus to the trigger element
|
||||
this._element.focus()
|
||||
}
|
||||
|
||||
_getConfig(config) {
|
||||
|
||||
Generated
+523
-304
File diff suppressed because it is too large
Load Diff
+11
-11
@@ -110,7 +110,7 @@
|
||||
"devDependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/markdown-remark": "^6.3.1",
|
||||
"@astrojs/mdx": "^4.2.4",
|
||||
"@astrojs/mdx": "^4.2.3",
|
||||
"@astrojs/prism": "^3.2.0",
|
||||
"@astrojs/sitemap": "^3.3.0",
|
||||
"@babel/cli": "^7.27.0",
|
||||
@@ -123,14 +123,14 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-replace": "^6.0.2",
|
||||
"@stackblitz/sdk": "^1.11.0",
|
||||
"@types/google.analytics": "^0.0.46",
|
||||
"@types/google.analytics": "^0.0.42",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/mime": "^3.0.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"astro": "^5.7.0",
|
||||
"astro": "^5.6.1",
|
||||
"astro-auto-import": "^0.4.4",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"bundlewatch": "^0.4.1",
|
||||
"bundlewatch": "^0.4.0",
|
||||
"clean-css-cli": "^5.6.3",
|
||||
"clipboard": "^2.0.11",
|
||||
"cross-env": "^7.0.3",
|
||||
@@ -144,8 +144,8 @@
|
||||
"github-slugger": "^2.0.0",
|
||||
"globby": "^14.1.0",
|
||||
"hammer-simulator": "0.0.1",
|
||||
"htmlparser2": "^10.0.0",
|
||||
"image-size": "^2.0.2",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"image-size": "^1.0.2",
|
||||
"ip": "^2.0.1",
|
||||
"jasmine": "^5.6.0",
|
||||
"jquery": "^3.7.1",
|
||||
@@ -160,14 +160,14 @@
|
||||
"karma-jasmine-html-reporter": "^2.1.0",
|
||||
"karma-rollup-preprocessor": "7.0.7",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"mime": "^4.0.7",
|
||||
"mime": "^3.0.0",
|
||||
"nodemon": "^3.1.9",
|
||||
"npm-run-all2": "^7.0.2",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-cli": "^11.0.1",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"prettier": "^2.8.4",
|
||||
"prettier-plugin-astro": "^0.8.0",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"remark": "^15.0.1",
|
||||
"remark-html": "^16.0.1",
|
||||
"rollup": "^4.38.0",
|
||||
@@ -179,7 +179,7 @@
|
||||
"stylelint": "^16.17.0",
|
||||
"stylelint-config-twbs-bootstrap": "^16.0.0",
|
||||
"terser": "^5.39.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"unist-util-visit": "^4.1.2",
|
||||
"vnu-jar": "24.10.17",
|
||||
"zod": "^3.20.6"
|
||||
},
|
||||
|
||||
@@ -11,10 +11,10 @@ const site = isDev
|
||||
? // In development mode, use the local dev server.
|
||||
'http://localhost:4321'
|
||||
: process.env.DEPLOY_PRIME_URL !== undefined
|
||||
? // If deploying on Netlify, use the `DEPLOY_PRIME_URL` environment variable.
|
||||
process.env.DEPLOY_PRIME_URL
|
||||
: // Otherwise, use the `baseURL` value defined in the `config.yml` file.
|
||||
getConfig().baseURL
|
||||
? // If deploying on Netlify, use the `DEPLOY_PRIME_URL` environment variable.
|
||||
process.env.DEPLOY_PRIME_URL
|
||||
: // Otherwise, use the `baseURL` value defined in the `config.yml` file.
|
||||
getConfig().baseURL
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
icon_color: indigo
|
||||
pages:
|
||||
- title: Introduction
|
||||
- title: Install
|
||||
- title: Download
|
||||
- title: Contents
|
||||
- title: Browsers & devices
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
interface Tab {
|
||||
id: string;
|
||||
title: string;
|
||||
active?: boolean;
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
tabs: Tab[];
|
||||
id?: string;
|
||||
}
|
||||
|
||||
const { tabs, id = "tabNav" } = Astro.props;
|
||||
---
|
||||
|
||||
<ul class="nav nav-tabs" id={id} role="tablist">
|
||||
{tabs.map((tab, index) => (
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
class={`nav-link ${tab.active ? 'active' : ''}`}
|
||||
id={`${tab.id}-tab`}
|
||||
data-bs-toggle="tab"
|
||||
data-bs-target={`#${tab.id}`}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-controls={tab.id}
|
||||
aria-selected={tab.active ? 'true' : 'false'}
|
||||
>
|
||||
{tab.title}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
{tabs.map((tab) => (
|
||||
<div
|
||||
class={`tab-pane ${tab.active ? 'active' : ''}`}
|
||||
id={tab.id}
|
||||
role="tabpanel"
|
||||
aria-labelledby={`${tab.id}-tab`}
|
||||
tabindex="0"
|
||||
>
|
||||
<Fragment set:html={tab.content} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Bootstrap tabs if they haven't been already
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Check if Bootstrap is available
|
||||
if (typeof bootstrap !== 'undefined') {
|
||||
const tabElements = document.querySelectorAll('[data-bs-toggle="tab"]');
|
||||
tabElements.forEach(el => {
|
||||
new bootstrap.Tab(el);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -14,7 +14,7 @@ interface Props {
|
||||
const { description, layout, thumbnail, title } = Astro.props
|
||||
|
||||
const socialImageUrl = new URL(getVersionedDocsPath(`assets/${thumbnail}`), Astro.site)
|
||||
const socialImageSize = await getStaticImageSize(`/docs/[version]/assets/${thumbnail}`)
|
||||
const socialImageSize = getStaticImageSize(`/docs/[version]/assets/${thumbnail}`)
|
||||
---
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
@@ -157,84 +157,3 @@ As part of Bootstrap’s evolving CSS variables approach, accordions now use loc
|
||||
### Sass variables
|
||||
|
||||
<ScssDocs name="accordion-variables" file="scss/_variables.scss" />
|
||||
|
||||
## Usage
|
||||
|
||||
The collapse plugin utilizes a few classes to handle the heavy lifting:
|
||||
|
||||
- `.collapse` hides the content
|
||||
- `.collapse.show` shows the content
|
||||
- `.collapsing` is added when the transition starts, and removed when it finishes
|
||||
|
||||
These classes can be found in `_transitions.scss`.
|
||||
|
||||
### Via data attributes
|
||||
|
||||
Just add `data-bs-toggle="collapse"` and a `data-bs-target` to the element to automatically assign control of one or more collapsible elements. The `data-bs-target` attribute accepts a CSS selector to apply the collapse to. Be sure to add the class `collapse` to the collapsible element. If you’d like it to default open, add the additional class `show`.
|
||||
|
||||
To add accordion group management to a collapsible area, add the data attribute `data-bs-parent="#selector"`.
|
||||
|
||||
### Via JavaScript
|
||||
|
||||
Enable manually with:
|
||||
|
||||
```js
|
||||
const accordionCollapseElementList = document.querySelectorAll('#myAccordion.collapse')
|
||||
const accordionCollapseList = [...accordionCollapseElementList].map(accordionCollapseEl => new bootstrap.Collapse(accordionCollapseEl))
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
<JsDataAttributes />
|
||||
|
||||
<BsTable>
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
`parent` | selector, DOM element | `null` | If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the `card` class). The attribute has to be set on the target collapsible area. |
|
||||
`toggle` | boolean | `true` | Toggles the collapsible element on invocation. |
|
||||
</BsTable>
|
||||
|
||||
### Methods
|
||||
|
||||
<Callout name="danger-async-methods" type="danger" />
|
||||
|
||||
Activates your content as a collapsible element. Accepts an optional options `object`.
|
||||
|
||||
You can create a collapse instance with the constructor, for example:
|
||||
|
||||
```js
|
||||
const bsCollapse = new bootstrap.Collapse('#myCollapse', {
|
||||
toggle: false
|
||||
})
|
||||
```
|
||||
|
||||
<BsTable>
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| `dispose` | Destroys an element’s collapse. (Removes stored data on the DOM element) |
|
||||
| `getInstance` | Static method which allows you to get the collapse instance associated to a DOM element, you can use it like this: `bootstrap.Collapse.getInstance(element)`. |
|
||||
| `getOrCreateInstance` | Static method which returns a collapse instance associated to a DOM element or create a new one in case it wasn’t initialized. You can use it like this: `bootstrap.Collapse.getOrCreateInstance(element)`. |
|
||||
| `hide` | Hides a collapsible element. **Returns to the caller before the collapsible element has actually been hidden** (e.g., before the `hidden.bs.collapse` event occurs). |
|
||||
| `show` | Shows a collapsible element. **Returns to the caller before the collapsible element has actually been shown** (e.g., before the `shown.bs.collapse` event occurs). |
|
||||
| `toggle` | Toggles a collapsible element to shown or hidden. **Returns to the caller before the collapsible element has actually been shown or hidden** (i.e. before the `shown.bs.collapse` or `hidden.bs.collapse` event occurs). |
|
||||
</BsTable>
|
||||
|
||||
### Events
|
||||
|
||||
Bootstrap’s collapse class exposes a few events for hooking into collapse functionality.
|
||||
|
||||
<BsTable>
|
||||
| Event type | Description |
|
||||
| --- | --- |
|
||||
| `hide.bs.collapse` | This event is fired immediately when the `hide` method has been called. |
|
||||
| `hidden.bs.collapse` | This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete). |
|
||||
| `show.bs.collapse` | This event fires immediately when the `show` instance method is called. |
|
||||
| `shown.bs.collapse` | This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete). |
|
||||
</BsTable>
|
||||
|
||||
```js
|
||||
const myCollapsible = document.getElementById('myCollapsible')
|
||||
myCollapsible.addEventListener('hidden.bs.collapse', event => {
|
||||
// do something...
|
||||
})
|
||||
```
|
||||
|
||||
@@ -30,12 +30,22 @@ Add `.active` to a `.list-group-item` to indicate the current active selection.
|
||||
<li class="list-group-item">And a fifth one</li>
|
||||
</ul>`} />
|
||||
|
||||
## Disabled items
|
||||
|
||||
Add `.disabled` to a `.list-group-item` to make it _appear_ disabled. Note that some elements with `.disabled` will also require custom JavaScript to fully disable their click events (e.g., links).
|
||||
|
||||
<Example code={`<ul class="list-group">
|
||||
<li class="list-group-item disabled" aria-disabled="true">A disabled item</li>
|
||||
<li class="list-group-item">A second item</li>
|
||||
<li class="list-group-item">A third item</li>
|
||||
<li class="list-group-item">A fourth item</li>
|
||||
<li class="list-group-item">And a fifth one</li>
|
||||
</ul>`} />
|
||||
|
||||
## Links and buttons
|
||||
|
||||
Use `<a>`s or `<button>`s to create _actionable_ list group items with hover, disabled, and active states by adding `.list-group-item-action`. We separate these pseudo-classes to ensure list groups made of non-interactive elements (like `<li>`s or `<div>`s) don’t provide a click or tap affordance.
|
||||
|
||||
Make `.list-group-item-action` instances _appear_ disabled by adding `.disabled`, and `aria-disabled="true"` to inform assistive technologies that the element is disabled. You may require additional JavaScript to fully disable links and buttons.
|
||||
|
||||
Be sure to **not use the standard `.btn` classes here**.
|
||||
|
||||
<Example code={`<div class="list-group">
|
||||
@@ -45,7 +55,7 @@ Be sure to **not use the standard `.btn` classes here**.
|
||||
<a href="#" class="list-group-item list-group-item-action">A second link item</a>
|
||||
<a href="#" class="list-group-item list-group-item-action">A third link item</a>
|
||||
<a href="#" class="list-group-item list-group-item-action">A fourth link item</a>
|
||||
<a href="#" class="list-group-item list-group-item-action disabled" aria-disabled="true">A disabled link item</a>
|
||||
<a class="list-group-item list-group-item-action disabled" aria-disabled="true">A disabled link item</a>
|
||||
</div>`} />
|
||||
|
||||
With `<button>`s, you can also make use of the `disabled` attribute instead of the `.disabled` class. Sadly, `<a>`s don’t support the disabled attribute.
|
||||
|
||||
@@ -115,19 +115,6 @@ A switch has the markup of a custom checkbox but uses the `.form-switch` class t
|
||||
<label class="form-check-label" for="switchCheckCheckedDisabled">Disabled checked switch checkbox input</label>
|
||||
</div>`} />
|
||||
|
||||
### Native switches
|
||||
|
||||
Progressively enhance your switches for mobile Safari (iOS 17.4+) by adding a `switch` attribute to your input to enable haptic feedback when toggling switches, just like native iOS switches. There are no style changes attached to using this attribute in Bootstrap as all our switches use custom styles.
|
||||
|
||||
<Example code={`<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" value="" id="checkNativeSwitch" switch>
|
||||
<label class="form-check-label" for="checkNativeSwitch">
|
||||
Native switch haptics
|
||||
</label>
|
||||
</div>`} />
|
||||
|
||||
Be sure to read more about [the switch attribute on the WebKit blog](https://webkit.org/blog/15054/an-html-switch-control/). Safari 17.4+ on macOS and iOS both have native-style switches in HTML while other browsers simply fall back to the standard checkbox appearance. Applying the attribute to a non-Bootstrap checkbox in more recent versions of Safari will render a native switch.
|
||||
|
||||
## Default (stacked)
|
||||
|
||||
By default, any number of checkboxes and radios that are immediate sibling will be vertically stacked and appropriately spaced with `.form-check`.
|
||||
@@ -253,7 +240,7 @@ Create button-like checkboxes and radio buttons by using `.btn` styles rather th
|
||||
<label class="btn" for="btn-check-6">Disabled</label>`} />
|
||||
|
||||
<Callout>
|
||||
Visually, these checkbox toggle buttons are identical to the [button plugin toggle buttons]([[docsref:/components/buttons#button-plugin]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked“/“not checked“ (since, despite their appearance, they are fundamentally still checkboxes), whereas the button plugin toggle buttons will be announced as “button“/“button pressed“. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
|
||||
Visually, these checkbox toggle buttons are identical to the [button plugin toggle buttons]([[docsref:/components/buttons#button-plugin]]). However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as “checked”/“not checked” (since, despite their appearance, they are fundamentally still checkboxes), whereas the button plugin toggle buttons will be announced as “button”/“button pressed”. The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
|
||||
</Callout>
|
||||
|
||||
### Radio toggle buttons
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: Install Bootstrap
|
||||
description: …
|
||||
toc: true
|
||||
---
|
||||
|
||||
import Tab from '../../../components/Tab.astro';
|
||||
|
||||
<Tab
|
||||
tabs={[
|
||||
{
|
||||
id: "home",
|
||||
title: "Default first",
|
||||
active: true,
|
||||
content: "default tab"
|
||||
},
|
||||
{
|
||||
id: "profile",
|
||||
title: "Second",
|
||||
content: "second tab"
|
||||
},
|
||||
{
|
||||
id: "messages",
|
||||
title: "Third",
|
||||
content: "third tab"
|
||||
}
|
||||
]}
|
||||
id="myTab"
|
||||
/>
|
||||
|
||||
```
|
||||
// Modern fluid sizing system using clamp()
|
||||
// Provides a simpler alternative to RFS while maintaining similar functionality
|
||||
|
||||
// Convert a px value to rem
|
||||
@function px-to-rem($px) {
|
||||
@return math.div($px, 16) * 1rem;
|
||||
}
|
||||
|
||||
// Strip unit from a value
|
||||
@function strip-unit($value) {
|
||||
@return math.div($value, ($value * 0 + 1));
|
||||
}
|
||||
|
||||
// Core fluid sizing mixin
|
||||
@mixin fluid-size($property, $min-size, $max-size, $min-vw: 320px, $max-vw: 1200px) {
|
||||
$min-size-rem: if(unit($min-size) == px, px-to-rem($min-size), $min-size);
|
||||
$max-size-rem: if(unit($max-size) == px, px-to-rem($max-size), $max-size);
|
||||
$min-vw-rem: if(unit($min-vw) == px, px-to-rem($min-vw), $min-vw);
|
||||
$max-vw-rem: if(unit($max-vw) == px, px-to-rem($max-vw), $max-vw);
|
||||
|
||||
#{$property}: clamp(
|
||||
#{$min-size-rem},
|
||||
#{$min-size-rem} + #{strip-unit($max-size-rem - $min-size-rem)} *
|
||||
((100vw - #{$min-vw-rem}) / #{strip-unit($max-vw-rem - $min-vw-rem)}),
|
||||
#{$max-size-rem}
|
||||
);
|
||||
}
|
||||
|
||||
// Fluid font-size mixin - direct replacement for rfs font-size
|
||||
@mixin fluid-font-size($size) {
|
||||
$min-size: if($size < 1.25rem, $size, 1.25rem);
|
||||
$max-size: $size;
|
||||
|
||||
@include fluid-size(font-size, $min-size, $max-size);
|
||||
}
|
||||
|
||||
// Fluid padding mixins
|
||||
@mixin fluid-padding($size) {
|
||||
@include fluid-size(padding, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-padding-top($size) {
|
||||
@include fluid-size(padding-top, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-padding-right($size) {
|
||||
@include fluid-size(padding-right, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-padding-bottom($size) {
|
||||
@include fluid-size(padding-bottom, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-padding-left($size) {
|
||||
@include fluid-size(padding-left, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
// Fluid margin mixins
|
||||
@mixin fluid-margin($size) {
|
||||
@include fluid-size(margin, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-margin-top($size) {
|
||||
@include fluid-size(margin-top, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-margin-right($size) {
|
||||
@include fluid-size(margin-right, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-margin-bottom($size) {
|
||||
@include fluid-size(margin-bottom, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
@mixin fluid-margin-left($size) {
|
||||
@include fluid-size(margin-left, $size * 0.5, $size);
|
||||
}
|
||||
|
||||
// Legacy compatibility mixins - these provide a bridge from RFS to the new system
|
||||
@mixin font-size($size) {
|
||||
@include fluid-font-size($size);
|
||||
}
|
||||
|
||||
@mixin padding($size) {
|
||||
@include fluid-padding($size);
|
||||
}
|
||||
|
||||
@mixin margin($size) {
|
||||
@include fluid-margin($size);
|
||||
}
|
||||
```
|
||||
@@ -1,14 +1,11 @@
|
||||
import path from 'node:path'
|
||||
import { promises as fs } from 'node:fs'
|
||||
import sizeOf from 'image-size'
|
||||
import { getDocsStaticFsPath } from './path'
|
||||
|
||||
export async function getStaticImageSize(imagePath: string) {
|
||||
const fullPath = path.join(getDocsStaticFsPath(), imagePath)
|
||||
const buffer = await fs.readFile(fullPath)
|
||||
const size = await sizeOf(buffer)
|
||||
export function getStaticImageSize(imagePath: string) {
|
||||
const size = sizeOf(path.join(getDocsStaticFsPath(), imagePath))
|
||||
|
||||
if (!size?.height || !size?.width) {
|
||||
if (!size.height || !size.width) {
|
||||
throw new Error(`Failed to get size of static image at '${imagePath}'.`)
|
||||
}
|
||||
|
||||
|
||||
@@ -147,8 +147,8 @@ function replaceInFrontmatter(record: Record<string, unknown>, replacer: (value:
|
||||
return typeof arrayValue === 'string'
|
||||
? replacer(arrayValue)
|
||||
: typeof arrayValue === 'object'
|
||||
? replaceInFrontmatter(arrayValue, replacer)
|
||||
: arrayValue
|
||||
? replaceInFrontmatter(arrayValue, replacer)
|
||||
: arrayValue
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user