@phun-ky/frameport 1.2.3 → 2.0.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.
package/README.md CHANGED
@@ -4,24 +4,26 @@
4
4
 
5
5
  > Frameport enables you to fake and display your responsive components in real life media queries!
6
6
 
7
- [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-green.svg)](http://makeapullrequest.com) [![SemVer 2.0](https://img.shields.io/badge/SemVer-2.0-green.svg)](http://semver.org/spec/v2.0.0.html) ![npm version](https://img.shields.io/npm/v/@phun-ky/frameport) ![issues](https://img.shields.io/github/issues/phun-ky/frameport) ![license](https://img.shields.io/npm/l/@phun-ky/frameport) ![size](https://img.shields.io/bundlephobia/min/@phun-ky/frameport) ![npm](https://img.shields.io/npm/dm/%40phun-ky/frameport) ![GitHub Repo stars](https://img.shields.io/github/stars/phun-ky/frameport)
8
-
9
- 1. [@phun-ky/frameport](#phun-kyframeport)
10
- 1. [About](#about)
11
- 2. [API](#api)
12
- 3. [Demo](#demo)
13
- 4. [Options](#options)
14
- 5. [Usage](#usage)
15
- 1. [Typescript](#typescript)
16
- 2. [ESM](#esm)
17
- 3. [Script](#script)
18
- 6. [Advanced usage](#advanced-usage)
19
- 1. [Lazy](#lazy)
20
- 7. [Features](#features)
21
- 8. [Via DOM](#via-dom)
22
- 1. [Use templates as a target](#use-templates-as-a-target)
23
- 2. [Use targets with different template](#use-targets-with-different-template)
24
- 1. [Allowed tags](#allowed-tags)
7
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-green.svg)](http://makeapullrequest.com) [![SemVer 2.0](https://img.shields.io/badge/SemVer-2.0-green.svg)](http://semver.org/spec/v2.0.0.html) ![npm version](https://img.shields.io/npm/v/@phun-ky/frameport) ![issues](https://img.shields.io/github/issues/phun-ky/frameport) ![license](https://img.shields.io/npm/l/@phun-ky/frameport) ![size](https://img.shields.io/bundlephobia/min/@phun-ky/frameport) ![npm](https://img.shields.io/npm/dm/%40phun-ky/frameport) ![GitHub Repo stars](https://img.shields.io/github/stars/phun-ky/frameport) [![codecov](https://codecov.io/gh/phun-ky/frameport/graph/badge.svg?token=VA91DL7ZLZ)](https://codecov.io/gh/phun-ky/frameport)
8
+
9
+ - [@phun-ky/frameport](#phun-kyframeport)
10
+ - [About](#about)
11
+ - [API](#api)
12
+ - [Demo](#demo)
13
+ - [Options](#options)
14
+ - [Usage](#usage)
15
+ - [Typescript](#typescript)
16
+ - [ESM](#esm)
17
+ - [Script](#script)
18
+ - [Advanced usage](#advanced-usage)
19
+ - [Lazy](#lazy)
20
+ - [Features](#features)
21
+ - [Via DOM](#via-dom)
22
+ - [Use templates as a target](#use-templates-as-a-target)
23
+ - [Use targets with different template](#use-targets-with-different-template)
24
+ - [Allowed tags](#allowed-tags)
25
+ - [Contributing](#contributing)
26
+ - [Sponsor me](#sponsor-me)
25
27
 
26
28
  ## About
27
29
 
@@ -62,7 +64,7 @@ Click [here for a demo on codepen.io](https://codepen.io/phun-ky/full/MWWWvLm)
62
64
 
63
65
  ### Typescript
64
66
 
65
- Types can be found in `@phun-ky/frameport/frameport.d.ts`.
67
+ Types can be found in `@phun-ky/frameport/dist/frameport.d.ts`.
66
68
 
67
69
  ### ESM
68
70
 
@@ -74,7 +76,7 @@ import frameport from '@phun-ky/frameport';
74
76
  // do stuff
75
77
  frameport(document.getElementById('target'), {
76
78
  width: 667,
77
- html: '<h1>FOO</h1>',
79
+ html: '<h1>FOO</h1>'
78
80
  });
79
81
  ```
80
82
 
@@ -176,7 +178,13 @@ export const lazy = (): void => {
176
178
  Place the `script` tag at the bottom of your page, right before the `</body>`-tag:
177
179
 
178
180
  ```html
179
- <script src="../path/to/@phun-ky/frameport/frameport.js"></script>
181
+ <script src="../path/to/@phun-ky/frameport/dist/frameport.js"></script>
182
+ ```
183
+
184
+ Or with a CDN:
185
+
186
+ ```html
187
+ <script src="https://unpkg.com/@phun-ky/frameport/dist/frameport.js"></script>
180
188
  ```
181
189
 
182
190
  And then follow the steps below to display the frameports you want :)
@@ -246,3 +254,15 @@ This approach is useful if you want to use a device decorator to mimic appearanc
246
254
  | data-frameport-class | Class names to be given the generated iframe |
247
255
  | data-frameport-viewports | The viewports to generate for examples. This is a string `wxh` for example: `375x667`. If you want more viewports, you can separate them with a comma: `375x667,360x740,768x1024`. **Required** |
248
256
  | data-frameport-headers | An array of HTTP headers to include when fetching the HTML content |
257
+
258
+ ## Contributing
259
+
260
+ If you want to contribute, please read the [CONTRIBUTING.md](https://github.com/phun-ky/frameport/blob/main/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/phun-ky/frameport/blob/main/CODE_OF_CONDUCT.md)
261
+
262
+ ## Sponsor me
263
+
264
+ I'm an Open Source evangelist, creating stuff that does not exist yet to help get rid of secondary activities and to enhance systems already in place, be it documentation or web sites.
265
+
266
+ The sponsorship is an unique opportunity to alleviate more hours for me to maintain my projects, create new ones and contribute to the large community we're all part of :)
267
+
268
+ [Support me with GitHub Sponsors](https://github.com/sponsors/phun-ky).
@@ -1,39 +1,39 @@
1
- /**
2
- * Example usage:
3
- * ```ts
4
- * const options: FrameportOptions = {
5
- * html: '<div>Hello, World!</div>',
6
- * height: '300',
7
- * width: 400,
8
- * className: 'my-embed',
9
- * style: 'color: blue;',
10
- * css: '.my-embed { background-color: yellow; }',
11
- * code: 'console.log("Embedded content");',
12
- * javascript: '/dummy.js',
13
- * headers: ['Authorization: Bearer Token']
14
- * };
15
- * ```
16
- */
17
- type FrameportFunctionType = () => void;
18
-
19
- /**
20
- * Extends the global Window interface to add custom properties.
21
- */
22
- declare global {
23
- interface Window {
24
- /**
25
- * Represents the frameport object for additional functionality.
26
- */
27
- frameport: any;
28
- }
1
+ /**
2
+ * Example usage:
3
+ * ```ts
4
+ * const options: FrameportOptions = {
5
+ * html: '<div>Hello, World!</div>',
6
+ * height: '300',
7
+ * width: 400,
8
+ * className: 'my-embed',
9
+ * style: 'color: blue;',
10
+ * css: '.my-embed { background-color: yellow; }',
11
+ * code: 'console.log("Embedded content");',
12
+ * javascript: '/dummy.js',
13
+ * headers: ['Authorization: Bearer Token']
14
+ * };
15
+ * ```
16
+ */
17
+ type FrameportFunctionType = () => void;
18
+
19
+ /**
20
+ * Extends the global Window interface to add custom properties.
21
+ */
22
+ declare global {
23
+ interface Window {
24
+ /**
25
+ * Represents the frameport object for additional functionality.
26
+ */
27
+ frameport: any;
28
+ }
29
29
  }
30
30
 
31
- declare const modes: {
32
- domReady: (frameport: FrameportFunctionType) => void;
33
- lazy: () => void;
34
- manual: (frameport: FrameportFunctionType) => void;
35
- activate: (frameport: FrameportFunctionType) => void;
36
- };
31
+ declare const modes: {
32
+ domReady: (frameport: FrameportFunctionType) => void;
33
+ lazy: () => void;
34
+ manual: (frameport: FrameportFunctionType) => void;
35
+ activate: (frameport: FrameportFunctionType) => void;
36
+ };
37
37
  declare const frameport: () => void;
38
38
 
39
39
  export { frameport as default, modes };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @phun-ky/frameport
3
+ * Create responsive documentation examples on the fly
4
+ * @author Alexander Vassbotn Røyne-Helgesen <alexander+frameport@phun-ky.net>
5
+ * @version 2.0.0
6
+ * @license
7
+ * Copyright (c) 2023 Alexander Vassbotn Røyne-Helgesen
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ * of this software and associated documentation files (the "Software"), to deal
11
+ * in the Software without restriction, including without limitation the rights
12
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be included in all
17
+ * copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ * SOFTWARE.
26
+ */
27
+ const t=t=>{let{style:e,css:r,code:a,javascript:o}=t;const{html:n,headers:s=[]}=t;return r=(t=>t&&""!==t?`<link rel="stylesheet" type="text/css" href="${window.location.protocol}//${window.location.host}${t.trim()}" />`:"")(r),o=(t=>t&&""!==t?`<script src="${window.location.protocol}//${window.location.host}${t.trim()}"><\/script>`:"")(o),a=(t=>t&&""!==t?`<script>${t.trim()}<\/script>`:"")(a),e=(t=>t&&""!==t?`<style type="text/css">${t}</style>`:"")(e),`<!DOCTYPE html>\n<html>\n<head>\n${s.join("\n")}\n${e}\n${r}\n</head>\n<body>\n${n||""}\n${o}\n${a}\n</body>\n</html>`},e=e=>((t,e)=>{const r=new Blob([t],{type:e});return URL.createObjectURL(r)})(t(e),"text/html"),r=async(t,e)=>{!t||!e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e||Array.isArray(e)&&0===e.length||0===Object.keys(e).length&&e.constructor===Object||(await new Promise(requestAnimationFrame),Array.isArray(e)?e.forEach((e=>t.style[e.key]=e.value)):Object.keys(e).forEach((r=>t.style[r]=e[r])))},a=t=>{const{className:a,height:o,width:n}=t,s=e(t),i=document.createElement("iframe"),c={};return i.src=s,i.setAttribute("data-rde-iframe",""),a&&""!==a?i.classList.add(a):c.border="none",c.width=`${n}px`,o&&(c.height=`${o}px`),r(i,c),i},o={clip:"rect(1px, 1px, 1px, 1px)",height:"1px",margin:"0",overflow:"hidden",position:"absolute",width:"1px"},n=['<meta charset="utf-8" />','<meta name="robots" content="none" />','<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />','<meta name="viewport" content="width=device-width, initial-scale=1" />'],s=(t,e)=>{if(!t||!e||e&&0===Object.keys(e).length)return;const{html:n,viewports:s,templateElement:i}=e;n&&""!==n&&(r(i,o),s?((t,e)=>{const{viewports:r}=e;if(!r||""===r)return;let o=[];r.includes(",")?o=[...o,...r.split(",")]:o.push(r);for(const r of o){const o=r.split("x"),[n,s]=o,i=a({...e,height:s,width:n});t.insertAdjacentElement("afterend",i)}})(t,e):((t,e)=>{const{width:r}=e;if(!r)return;const o=a(e);t.append(o)})(t,e))},i=t=>{let e=[...n];return t&&(Array.isArray(t)?e=[...e,...t].map((t=>t.trim())):t.includes(",")?e=[...e,...t.split(",")].map((t=>t.trim())):""!==t&&e.push(t.trim())),e},c=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},l=()=>{const t=new IntersectionObserver(((t,e)=>{t.forEach((t=>{if(t.intersectionRatio>0){const{dataset:{frameportTemplate:r,frameportVh:a,frameportVw:o,frameportCss:n,frameportStyle:c,frameportCode:l,frameportJs:m,frameportClass:p,frameportHeaders:d,frameportViewports:h}}=t.target;let f=t.target.innerHTML,u=t.target;if(r){const t=document.querySelector(r);t&&(f=t.innerHTML,u=t)}const y={templateSelector:r,templateElement:u,height:a,width:o,html:f,css:n,style:c,code:l,javascript:m,className:p,headers:i(d),viewports:h};s(t.target,y),e.unobserve(t.target)}}))}));document.querySelectorAll("[data-frameport]").forEach((e=>{t.observe(e)}))},m=t=>{window.frameport=t},p=t=>{const e=document.currentScript;if(e){const r=e.getAttribute("src");r&&r.includes("frameport.js")&&(e.hasAttribute("data-manual")?m(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?c(t):e.hasAttribute("data-lazy")?l():c(t))}},d={domReady:c,lazy:l,manual:m,activate:p},h=()=>{document.querySelectorAll("[data-frameport-iframe]").forEach((t=>t.remove()));document.querySelectorAll("[data-frameport]").forEach((t=>{const{dataset:{frameportTemplate:e,frameportVh:r,frameportVw:a,frameportCss:o,frameportStyle:n,frameportCode:c,frameportJs:l,frameportClass:m,frameportHeaders:p,frameportViewports:d}}=t;let h=t.innerHTML,f=t;if(e){const t=document.querySelector(e);t&&(h=t.innerHTML,f=t)}const u={templateSelector:e,templateElement:f,height:r,width:a,html:h,css:o,style:n,code:c,javascript:l,className:m,headers:i(p),viewports:d};s(t,u)}))};p(h);export{h as default,d as modes};
28
+ //# sourceMappingURL=frameport.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameport.esm.js","sources":["../src/utils/iframe.ts","../src/utils/source.ts","../src/utils/css.ts","../src/utils/js.ts","../src/utils/code.ts","../src/utils/style.ts","../src/utils/page.ts","../src/utils/blob.ts","../src/utils/styles.ts","../src/utils/wait.ts","../src/utils/create.ts","../src/constants/index.ts","../src/features/dom.ts","../src/config/generate-viewports.ts","../src/config/generate.ts","../src/utils/headers.ts","../src/config/browser.ts","../src/main.ts"],"sourcesContent":["/**\n * Create and return an iframe element.\n *\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const createIframe = (): HTMLIFrameElement =>\n document.createElement('iframe');\n","import { FrameportOptions } from '../types';\n\nimport { getCode } from './code';\nimport { getCSS } from './css';\nimport { getJavaScript } from './js';\nimport { getStyle } from './style';\n\n/**\n * Generate the source code for an HTML page based on the provided options.\n *\n * @param {FrameportOptions} options - The options for generating the HTML page source.\n * @returns {string} - The generated HTML source code as a string.\n */\nexport const getSource = (options: FrameportOptions): string => {\n let { style, css, code, javascript } = options;\n\n const { html, headers = [] } = options;\n\n css = getCSS(css);\n javascript = getJavaScript(javascript);\n code = getCode(code);\n style = getStyle(style);\n\n return `<!DOCTYPE html>\n<html>\n<head>\n${headers.join('\\n')}\n${style}\n${css}\n</head>\n<body>\n${html || ''}\n${javascript}\n${code}\n</body>\n</html>`;\n};\n","/**\n * Generate a CSS link tag based on the provided URL.\n *\n * @param {string | undefined} css - The URL of the CSS file.\n * @returns {string} - A CSS link tag.\n */\nexport const getCSS = (css: string | undefined): string => {\n if (css && css !== '') {\n return `<link rel=\"stylesheet\" type=\"text/css\" href=\"${window.location.protocol}//${window.location.host}${css.trim()}\" />`;\n }\n\n return '';\n};\n","/**\n * Generate a script tag for the specified JavaScript file.\n *\n * @param {string | undefined} javascript - The path to the JavaScript file.\n * @returns {string} - The generated script tag or an empty string if no JavaScript path is provided.\n */\nexport const getJavaScript = (javascript: string | undefined): string => {\n if (javascript && javascript !== '') {\n return `<script src=\"${window.location.protocol}//${window.location.host}${javascript.trim()}\"></script>`;\n }\n\n return '';\n};\n","/**\n * Get a script element containing the provided code if available.\n *\n * @param {string | undefined} code - The code to include in the script element.\n * @returns {string} - The script element or an empty string if code is not available.\n */\nexport const getCode = (code: string | undefined): string => {\n if (code && code !== '') {\n return `<script>${code.trim()}</script>`;\n }\n\n return '';\n};\n","/**\n * Generate a style element based on the provided CSS styles.\n *\n * @param {string | undefined} style - The CSS styles to include in the style element.\n * @returns {string} - The style element as a string or an empty string if no styles are provided.\n */\nexport const getStyle = (style: string | undefined): string => {\n if (style && style !== '') {\n return `<style type=\"text/css\">${style}</style>`;\n }\n\n return '';\n};\n","import { getBlobURL } from './blob';\nimport { getSource } from './source';\n\n/**\n * Get the URL of a generated HTML page based on the provided options.\n *\n * @param {object} options - The options for generating the HTML page.\n * @returns {string} - The URL of the generated HTML page as a Blob URL.\n */\nexport const getGeneratedPageURL = (options) => {\n const source = getSource(options);\n\n return getBlobURL(source, 'text/html');\n};\n","/**\n * Generates a Blob URL from HTML content with the specified MIME type.\n *\n * @param {string} html - The HTML content to create a Blob from.\n * @param {string} type - The MIME type of the Blob (e.g., 'text/html', 'image/jpeg').\n * @returns {string} - The generated Blob URL.\n */\nexport const getBlobURL = (html: string, type: string): string => {\n const blob = new Blob([html], { type });\n\n return URL.createObjectURL(blob);\n};\n","/* eslint no-console:0 */\nimport { waitForFrame } from './wait';\n\n/**\n * Adds CSS styles to an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to apply styles to.\n * @param {object | Array<{ key: string; value: string }>} styles - An object or an array of objects containing CSS styles to apply.\n * @returns {Promise<void>} - A Promise that resolves after styles are applied.\n *\n * @example\n * ```ts\n * // Apply styles as an object\n * const element = document.getElementById('my-element');\n * await add(element, { color: 'red', fontSize: '16px' });\n *\n * // Apply styles as an array of objects\n * const styles = [\n * { key: 'color', value: 'blue' },\n * { key: 'backgroundColor', value: 'yellow' }\n * ];\n * await add(element, styles);\n * ```\n */\nexport const add = async (\n el: HTMLElement,\n styles: object | { key: string; value: string }[]\n): Promise<void> => {\n if (\n !el ||\n !styles ||\n typeof styles === 'string' ||\n typeof styles === 'number' ||\n typeof styles === 'boolean' ||\n (Array.isArray(styles) && styles.length === 0) ||\n (Object.keys(styles).length === 0 && styles.constructor === Object)\n ) {\n return;\n }\n\n await waitForFrame();\n\n if (Array.isArray(styles)) {\n styles.forEach(\n (style: { key: string; value: string }) =>\n (el.style[style.key] = style.value)\n );\n } else {\n Object.keys(styles).forEach((key) => (el.style[key] = styles[key]));\n }\n};\n\n/**\n * Gets the computed CSS styles of an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to get computed styles from.\n * @returns {Promise<CSSStyleDeclaration>} - A Promise that resolves with the computed CSS styles.\n *\n * @example\n * ```ts\n * // Get computed styles of an element\n * const element = document.getElementById('my-element');\n * const computedStyles = await get(element);\n * console.log(computedStyles.color); // Logs the color property value\n * ```\n */\nexport const get = async (el: HTMLElement): Promise<CSSStyleDeclaration> => {\n await waitForFrame();\n\n return getComputedStyle(el, null);\n};\n","/**\n * Waits for the next animation frame using requestAnimationFrame.\n *\n * @returns {Promise<number>} - A Promise that resolves with the timestamp of the next animation frame.\n *\n * @example\n * ```ts\n * // Wait for the next animation frame and get the rect\n * await waitForFrame();\n * const rect = el.getBoundingClientRect();\n * // Wait for the next animation frame and get the timestamp\n * const timestamp = await waitForFrame();\n * ```\n */\nexport const waitForFrame = (): Promise<number> =>\n new Promise<number>(requestAnimationFrame);\n","import { FrameportOptions } from '../types';\nimport { createIframe } from '../utils/iframe';\nimport { getGeneratedPageURL } from '../utils/page';\nimport { add as addStyles } from '../utils/styles';\n\n/**\n * Create an iframe element with specified options and styles.\n *\n * @param {FrameportOptions} options - The options for creating the iframe.\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const create = (options: FrameportOptions): HTMLIFrameElement => {\n const { className, height, width } = options;\n const url = getGeneratedPageURL(options);\n const iframeElement = createIframe();\n const iframeStyle = {};\n\n iframeElement.src = url;\n iframeElement.setAttribute('data-rde-iframe', '');\n\n if (!className || className === '') {\n iframeStyle['border'] = 'none';\n } else {\n iframeElement.classList.add(className);\n }\n\n iframeStyle['width'] = `${width}px`;\n\n if (height) {\n iframeStyle['height'] = `${height}px`;\n }\n\n addStyles(iframeElement, iframeStyle);\n\n return iframeElement;\n};\n","/**\n * Style object for hiding an element in the HTML.\n *\n * @type {{ clip: string, height: string, margin: string, overflow: string, position: string, width: string }}\n */\nexport const HIDE_TEMPLATE_STYLE: {\n clip: string;\n height: string;\n margin: string;\n overflow: string;\n position: string;\n width: string;\n} = {\n clip: 'rect(1px, 1px, 1px, 1px)',\n height: '1px',\n margin: '0',\n overflow: 'hidden',\n position: 'absolute',\n width: '1px'\n};\n\n/**\n * Default meta headers for an HTML document.\n *\n * @type {string[]}\n */\nexport const DEFAULT_HEADERS: string[] = [\n '<meta charset=\"utf-8\" />',\n '<meta name=\"robots\" content=\"none\" />',\n '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />'\n];\n","import { generate } from '../config/generate';\nimport { generateViewports } from '../config/generate-viewports';\nimport { HIDE_TEMPLATE_STYLE } from '../constants';\nimport { FrameportOptions } from '../types';\nimport { add as addStyles } from '../utils/styles';\n\n/**\n * Generate iframes into the DOM, possibly generating viewports.\n *\n * @param {HTMLElement} targetElement - The target HTML element.\n * @param {FrameportOptions} options - The options for the iframe.\n * @returns {void}\n */\nconst dom = (targetElement: HTMLElement, options: FrameportOptions): void => {\n if (\n !targetElement ||\n !options ||\n (options && Object.keys(options).length === 0)\n )\n return;\n\n const { html, viewports, templateElement } = options;\n\n if (!html || html === '') return;\n\n addStyles(templateElement as HTMLElement, HIDE_TEMPLATE_STYLE);\n\n if (viewports) {\n generateViewports(targetElement, options);\n } else {\n generate(targetElement, options);\n }\n};\n\nexport default dom;\n","import { FrameportOptions } from '../types';\nimport { create } from '../utils/create';\n\n/**\n * Generate multiple iframe elements for different viewports and append them to a target element.\n *\n * @param {HTMLElement} target - The target HTML element to insert iframes after.\n * @param {FrameportOptions} options - The options for generating the iframes.\n * @returns {void}\n */\nexport const generateViewports = (\n target: HTMLElement,\n options: FrameportOptions\n): void => {\n const { viewports } = options;\n\n if (!viewports || viewports === '') return;\n\n let screens: string[] = [];\n\n if (viewports.includes(',')) screens = [...screens, ...viewports.split(',')];\n else screens.push(viewports);\n\n for (const viewPort of screens) {\n const values = viewPort.split('x');\n const [width, height] = values;\n const iframeElement = create({ ...options, height, width });\n\n target.insertAdjacentElement('afterend', iframeElement);\n }\n};\n","import { FrameportOptions } from '../types';\nimport { create } from '../utils/create';\n\n/**\n * Generate an iframe with the given options and append it to a target element.\n *\n * @param {HTMLElement} targetElement - The target HTML element to append the iframe to.\n * @param {FrameportOptions} options - The options for generating the iframe.\n * @returns {void}\n */\nexport const generate = (\n targetElement: HTMLElement,\n options: FrameportOptions\n): void => {\n const { width } = options;\n\n if (!width) return;\n\n const iframeElement = create(options);\n\n targetElement.append(iframeElement);\n};\n","import { DEFAULT_HEADERS } from '../constants';\n\n/**\n * Get headers for the iframe generated\n *\n * @param {string|string[]|null|undefined} rdeHeaders - The custom headers to include.\n * @returns {string[]} - An array of headers, including default and custom headers.\n */\nexport const getHeaders = (\n rdeHeaders: string | string[] | null | undefined\n): string[] => {\n let headers: string[] = [...DEFAULT_HEADERS];\n\n if (rdeHeaders) {\n if (Array.isArray(rdeHeaders)) {\n headers = [...headers, ...rdeHeaders].map((h) => h.trim());\n } else if (rdeHeaders.includes(',')) {\n headers = [...headers, ...rdeHeaders.split(',')].map((h) => h.trim());\n } else if (rdeHeaders !== '') {\n headers.push(rdeHeaders.trim());\n }\n }\n\n return headers;\n};\n","/* eslint no-console:0 */\nimport dom from '../features/dom';\nimport { FrameportFunctionType } from '../types';\nimport { getHeaders } from '../utils/headers';\n\n/**\n * A function to initialize frameport when the DOM is ready.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // domReady(myRDE);\n * ```\n */\nexport const domReady = (frameport: FrameportFunctionType): void => {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n frameport();\n });\n } else {\n // `DOMContentLoaded` already fired\n frameport();\n }\n};\n\n/**\n * A function to initialize lazy frameport functionality.\n *\n * @example\n * ```ts\n * // Usage example:\n * // lazy();\n * ```\n */\nexport const lazy = (): void => {\n const frameportObserverTarget = new IntersectionObserver((els, observer) => {\n els.forEach((el: IntersectionObserverEntry) => {\n if (el.intersectionRatio > 0) {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports\n }\n } = el.target as HTMLElement;\n\n let html = el.target.innerHTML;\n let templateElementToUse = el.target as HTMLElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports\n };\n\n dom(el.target as HTMLElement, options);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-frameport]').forEach((el) => {\n frameportObserverTarget.observe(el);\n });\n};\n\n/**\n * A function to manually activate frameport.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // manual(myRDE);\n * ```\n */\nexport const manual = (frameport: FrameportFunctionType): void => {\n window.frameport = frameport;\n};\n\n/**\n * A function to activate frameport based on script attributes.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // activate(myRDE);\n * ```\n */\nexport const activate = (frameport: FrameportFunctionType): void => {\n const script = document.currentScript;\n\n if (script) {\n const frameportScriptSrc = script.getAttribute('src');\n\n if (frameportScriptSrc && frameportScriptSrc.includes('frameport.js')) {\n if (script.hasAttribute('data-manual')) {\n manual(frameport);\n } else if (script.hasAttribute('data-instant')) {\n frameport();\n } else if (script.hasAttribute('data-dom')) {\n domReady(frameport);\n } else if (script.hasAttribute('data-lazy')) {\n lazy();\n } else {\n domReady(frameport);\n }\n }\n }\n};\n","/* eslint-disable import/no-unused-modules */\nimport { domReady, lazy, manual, activate } from './config/browser';\nimport dom from './features/dom';\nimport { getHeaders } from './utils/headers';\n\nexport const modes = {\n domReady,\n lazy,\n manual,\n activate\n};\n\nconst frameport = () => {\n document\n .querySelectorAll('[data-frameport-iframe]')\n .forEach((iframe) => iframe.remove());\n\n const elsToBeTransformedTemplate =\n document.querySelectorAll('[data-frameport]');\n\n elsToBeTransformedTemplate.forEach((targetElement: HTMLElement) => {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports\n }\n } = targetElement;\n\n let html = targetElement.innerHTML;\n let templateElementToUse = targetElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports\n };\n\n dom(targetElement, options);\n });\n};\n\nexport default frameport;\n\nactivate(frameport);\n"],"names":["getSource","options","style","css","code","javascript","html","headers","window","location","protocol","host","trim","getCSS","getJavaScript","getCode","getStyle","join","getGeneratedPageURL","type","blob","Blob","URL","createObjectURL","getBlobURL","add","async","el","styles","Array","isArray","length","Object","keys","constructor","Promise","requestAnimationFrame","forEach","key","value","create","className","height","width","url","iframeElement","document","createElement","iframeStyle","src","setAttribute","classList","addStyles","HIDE_TEMPLATE_STYLE","clip","margin","overflow","position","DEFAULT_HEADERS","dom","targetElement","viewports","templateElement","target","screens","includes","split","push","viewPort","values","insertAdjacentElement","generateViewports","append","generate","getHeaders","rdeHeaders","map","h","domReady","frameport","readyState","addEventListener","lazy","frameportObserverTarget","IntersectionObserver","els","observer","intersectionRatio","dataset","frameportTemplate","templateSelector","frameportVh","frameportVw","frameportCss","frameportStyle","frameportCode","frameportJs","frameportClass","frameportHeaders","frameportViewports","innerHTML","templateElementToUse","querySelector","unobserve","querySelectorAll","observe","manual","activate","script","currentScript","frameportScriptSrc","getAttribute","hasAttribute","modes","iframe","remove"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @phun-ky/frameport
3
+ * Create responsive documentation examples on the fly
4
+ * @author Alexander Vassbotn Røyne-Helgesen <alexander+frameport@phun-ky.net>
5
+ * @version 2.0.0
6
+ * @license
7
+ * Copyright (c) 2023 Alexander Vassbotn Røyne-Helgesen
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ * of this software and associated documentation files (the "Software"), to deal
11
+ * in the Software without restriction, including without limitation the rights
12
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be included in all
17
+ * copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ * SOFTWARE.
26
+ */
27
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).frameport={})}(this,(function(t){"use strict";const e=t=>{let{style:e,css:r,code:o,javascript:a}=t;const{html:n,headers:s=[]}=t;return r=(t=>t&&""!==t?`<link rel="stylesheet" type="text/css" href="${window.location.protocol}//${window.location.host}${t.trim()}" />`:"")(r),a=(t=>t&&""!==t?`<script src="${window.location.protocol}//${window.location.host}${t.trim()}"><\/script>`:"")(a),o=(t=>t&&""!==t?`<script>${t.trim()}<\/script>`:"")(o),e=(t=>t&&""!==t?`<style type="text/css">${t}</style>`:"")(e),`<!DOCTYPE html>\n<html>\n<head>\n${s.join("\n")}\n${e}\n${r}\n</head>\n<body>\n${n||""}\n${a}\n${o}\n</body>\n</html>`},r=t=>((t,e)=>{const r=new Blob([t],{type:e});return URL.createObjectURL(r)})(e(t),"text/html"),o=async(t,e)=>{!t||!e||"string"==typeof e||"number"==typeof e||"boolean"==typeof e||Array.isArray(e)&&0===e.length||0===Object.keys(e).length&&e.constructor===Object||(await new Promise(requestAnimationFrame),Array.isArray(e)?e.forEach((e=>t.style[e.key]=e.value)):Object.keys(e).forEach((r=>t.style[r]=e[r])))},a=t=>{const{className:e,height:a,width:n}=t,s=r(t),i=document.createElement("iframe"),c={};return i.src=s,i.setAttribute("data-rde-iframe",""),e&&""!==e?i.classList.add(e):c.border="none",c.width=`${n}px`,a&&(c.height=`${a}px`),o(i,c),i},n={clip:"rect(1px, 1px, 1px, 1px)",height:"1px",margin:"0",overflow:"hidden",position:"absolute",width:"1px"},s=['<meta charset="utf-8" />','<meta name="robots" content="none" />','<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />','<meta name="viewport" content="width=device-width, initial-scale=1" />'],i=(t,e)=>{if(!t||!e||e&&0===Object.keys(e).length)return;const{html:r,viewports:s,templateElement:i}=e;r&&""!==r&&(o(i,n),s?((t,e)=>{const{viewports:r}=e;if(!r||""===r)return;let o=[];r.includes(",")?o=[...o,...r.split(",")]:o.push(r);for(const r of o){const o=r.split("x"),[n,s]=o,i=a({...e,height:s,width:n});t.insertAdjacentElement("afterend",i)}})(t,e):((t,e)=>{const{width:r}=e;if(!r)return;const o=a(e);t.append(o)})(t,e))},c=t=>{let e=[...s];return t&&(Array.isArray(t)?e=[...e,...t].map((t=>t.trim())):t.includes(",")?e=[...e,...t.split(",")].map((t=>t.trim())):""!==t&&e.push(t.trim())),e},l=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},m=()=>{const t=new IntersectionObserver(((t,e)=>{t.forEach((t=>{if(t.intersectionRatio>0){const{dataset:{frameportTemplate:r,frameportVh:o,frameportVw:a,frameportCss:n,frameportStyle:s,frameportCode:l,frameportJs:m,frameportClass:p,frameportHeaders:d,frameportViewports:f}}=t.target;let h=t.target.innerHTML,u=t.target;if(r){const t=document.querySelector(r);t&&(h=t.innerHTML,u=t)}const y={templateSelector:r,templateElement:u,height:o,width:a,html:h,css:n,style:s,code:l,javascript:m,className:p,headers:c(d),viewports:f};i(t.target,y),e.unobserve(t.target)}}))}));document.querySelectorAll("[data-frameport]").forEach((e=>{t.observe(e)}))},p=t=>{window.frameport=t},d=t=>{const e=document.currentScript;if(e){const r=e.getAttribute("src");r&&r.includes("frameport.js")&&(e.hasAttribute("data-manual")?p(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?l(t):e.hasAttribute("data-lazy")?m():l(t))}},f={domReady:l,lazy:m,manual:p,activate:d},h=()=>{document.querySelectorAll("[data-frameport-iframe]").forEach((t=>t.remove()));document.querySelectorAll("[data-frameport]").forEach((t=>{const{dataset:{frameportTemplate:e,frameportVh:r,frameportVw:o,frameportCss:a,frameportStyle:n,frameportCode:s,frameportJs:l,frameportClass:m,frameportHeaders:p,frameportViewports:d}}=t;let f=t.innerHTML,h=t;if(e){const t=document.querySelector(e);t&&(f=t.innerHTML,h=t)}const u={templateSelector:e,templateElement:h,height:r,width:o,html:f,css:a,style:n,code:s,javascript:l,className:m,headers:c(p),viewports:d};i(t,u)}))};d(h),t.default=h,t.modes=f,Object.defineProperty(t,"__esModule",{value:!0})}));
28
+ //# sourceMappingURL=frameport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameport.js","sources":["../src/utils/iframe.ts","../src/utils/source.ts","../src/utils/css.ts","../src/utils/js.ts","../src/utils/code.ts","../src/utils/style.ts","../src/utils/page.ts","../src/utils/blob.ts","../src/utils/styles.ts","../src/utils/wait.ts","../src/utils/create.ts","../src/constants/index.ts","../src/features/dom.ts","../src/config/generate-viewports.ts","../src/config/generate.ts","../src/utils/headers.ts","../src/config/browser.ts","../src/main.ts"],"sourcesContent":["/**\n * Create and return an iframe element.\n *\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const createIframe = (): HTMLIFrameElement =>\n document.createElement('iframe');\n","import { FrameportOptions } from '../types';\n\nimport { getCode } from './code';\nimport { getCSS } from './css';\nimport { getJavaScript } from './js';\nimport { getStyle } from './style';\n\n/**\n * Generate the source code for an HTML page based on the provided options.\n *\n * @param {FrameportOptions} options - The options for generating the HTML page source.\n * @returns {string} - The generated HTML source code as a string.\n */\nexport const getSource = (options: FrameportOptions): string => {\n let { style, css, code, javascript } = options;\n\n const { html, headers = [] } = options;\n\n css = getCSS(css);\n javascript = getJavaScript(javascript);\n code = getCode(code);\n style = getStyle(style);\n\n return `<!DOCTYPE html>\n<html>\n<head>\n${headers.join('\\n')}\n${style}\n${css}\n</head>\n<body>\n${html || ''}\n${javascript}\n${code}\n</body>\n</html>`;\n};\n","/**\n * Generate a CSS link tag based on the provided URL.\n *\n * @param {string | undefined} css - The URL of the CSS file.\n * @returns {string} - A CSS link tag.\n */\nexport const getCSS = (css: string | undefined): string => {\n if (css && css !== '') {\n return `<link rel=\"stylesheet\" type=\"text/css\" href=\"${window.location.protocol}//${window.location.host}${css.trim()}\" />`;\n }\n\n return '';\n};\n","/**\n * Generate a script tag for the specified JavaScript file.\n *\n * @param {string | undefined} javascript - The path to the JavaScript file.\n * @returns {string} - The generated script tag or an empty string if no JavaScript path is provided.\n */\nexport const getJavaScript = (javascript: string | undefined): string => {\n if (javascript && javascript !== '') {\n return `<script src=\"${window.location.protocol}//${window.location.host}${javascript.trim()}\"></script>`;\n }\n\n return '';\n};\n","/**\n * Get a script element containing the provided code if available.\n *\n * @param {string | undefined} code - The code to include in the script element.\n * @returns {string} - The script element or an empty string if code is not available.\n */\nexport const getCode = (code: string | undefined): string => {\n if (code && code !== '') {\n return `<script>${code.trim()}</script>`;\n }\n\n return '';\n};\n","/**\n * Generate a style element based on the provided CSS styles.\n *\n * @param {string | undefined} style - The CSS styles to include in the style element.\n * @returns {string} - The style element as a string or an empty string if no styles are provided.\n */\nexport const getStyle = (style: string | undefined): string => {\n if (style && style !== '') {\n return `<style type=\"text/css\">${style}</style>`;\n }\n\n return '';\n};\n","import { getBlobURL } from './blob';\nimport { getSource } from './source';\n\n/**\n * Get the URL of a generated HTML page based on the provided options.\n *\n * @param {object} options - The options for generating the HTML page.\n * @returns {string} - The URL of the generated HTML page as a Blob URL.\n */\nexport const getGeneratedPageURL = (options) => {\n const source = getSource(options);\n\n return getBlobURL(source, 'text/html');\n};\n","/**\n * Generates a Blob URL from HTML content with the specified MIME type.\n *\n * @param {string} html - The HTML content to create a Blob from.\n * @param {string} type - The MIME type of the Blob (e.g., 'text/html', 'image/jpeg').\n * @returns {string} - The generated Blob URL.\n */\nexport const getBlobURL = (html: string, type: string): string => {\n const blob = new Blob([html], { type });\n\n return URL.createObjectURL(blob);\n};\n","/* eslint no-console:0 */\nimport { waitForFrame } from './wait';\n\n/**\n * Adds CSS styles to an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to apply styles to.\n * @param {object | Array<{ key: string; value: string }>} styles - An object or an array of objects containing CSS styles to apply.\n * @returns {Promise<void>} - A Promise that resolves after styles are applied.\n *\n * @example\n * ```ts\n * // Apply styles as an object\n * const element = document.getElementById('my-element');\n * await add(element, { color: 'red', fontSize: '16px' });\n *\n * // Apply styles as an array of objects\n * const styles = [\n * { key: 'color', value: 'blue' },\n * { key: 'backgroundColor', value: 'yellow' }\n * ];\n * await add(element, styles);\n * ```\n */\nexport const add = async (\n el: HTMLElement,\n styles: object | { key: string; value: string }[]\n): Promise<void> => {\n if (\n !el ||\n !styles ||\n typeof styles === 'string' ||\n typeof styles === 'number' ||\n typeof styles === 'boolean' ||\n (Array.isArray(styles) && styles.length === 0) ||\n (Object.keys(styles).length === 0 && styles.constructor === Object)\n ) {\n return;\n }\n\n await waitForFrame();\n\n if (Array.isArray(styles)) {\n styles.forEach(\n (style: { key: string; value: string }) =>\n (el.style[style.key] = style.value)\n );\n } else {\n Object.keys(styles).forEach((key) => (el.style[key] = styles[key]));\n }\n};\n\n/**\n * Gets the computed CSS styles of an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to get computed styles from.\n * @returns {Promise<CSSStyleDeclaration>} - A Promise that resolves with the computed CSS styles.\n *\n * @example\n * ```ts\n * // Get computed styles of an element\n * const element = document.getElementById('my-element');\n * const computedStyles = await get(element);\n * console.log(computedStyles.color); // Logs the color property value\n * ```\n */\nexport const get = async (el: HTMLElement): Promise<CSSStyleDeclaration> => {\n await waitForFrame();\n\n return getComputedStyle(el, null);\n};\n","/**\n * Waits for the next animation frame using requestAnimationFrame.\n *\n * @returns {Promise<number>} - A Promise that resolves with the timestamp of the next animation frame.\n *\n * @example\n * ```ts\n * // Wait for the next animation frame and get the rect\n * await waitForFrame();\n * const rect = el.getBoundingClientRect();\n * // Wait for the next animation frame and get the timestamp\n * const timestamp = await waitForFrame();\n * ```\n */\nexport const waitForFrame = (): Promise<number> =>\n new Promise<number>(requestAnimationFrame);\n","import { FrameportOptions } from '../types';\nimport { createIframe } from '../utils/iframe';\nimport { getGeneratedPageURL } from '../utils/page';\nimport { add as addStyles } from '../utils/styles';\n\n/**\n * Create an iframe element with specified options and styles.\n *\n * @param {FrameportOptions} options - The options for creating the iframe.\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const create = (options: FrameportOptions): HTMLIFrameElement => {\n const { className, height, width } = options;\n const url = getGeneratedPageURL(options);\n const iframeElement = createIframe();\n const iframeStyle = {};\n\n iframeElement.src = url;\n iframeElement.setAttribute('data-rde-iframe', '');\n\n if (!className || className === '') {\n iframeStyle['border'] = 'none';\n } else {\n iframeElement.classList.add(className);\n }\n\n iframeStyle['width'] = `${width}px`;\n\n if (height) {\n iframeStyle['height'] = `${height}px`;\n }\n\n addStyles(iframeElement, iframeStyle);\n\n return iframeElement;\n};\n","/**\n * Style object for hiding an element in the HTML.\n *\n * @type {{ clip: string, height: string, margin: string, overflow: string, position: string, width: string }}\n */\nexport const HIDE_TEMPLATE_STYLE: {\n clip: string;\n height: string;\n margin: string;\n overflow: string;\n position: string;\n width: string;\n} = {\n clip: 'rect(1px, 1px, 1px, 1px)',\n height: '1px',\n margin: '0',\n overflow: 'hidden',\n position: 'absolute',\n width: '1px'\n};\n\n/**\n * Default meta headers for an HTML document.\n *\n * @type {string[]}\n */\nexport const DEFAULT_HEADERS: string[] = [\n '<meta charset=\"utf-8\" />',\n '<meta name=\"robots\" content=\"none\" />',\n '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />'\n];\n","import { generate } from '../config/generate';\nimport { generateViewports } from '../config/generate-viewports';\nimport { HIDE_TEMPLATE_STYLE } from '../constants';\nimport { FrameportOptions } from '../types';\nimport { add as addStyles } from '../utils/styles';\n\n/**\n * Generate iframes into the DOM, possibly generating viewports.\n *\n * @param {HTMLElement} targetElement - The target HTML element.\n * @param {FrameportOptions} options - The options for the iframe.\n * @returns {void}\n */\nconst dom = (targetElement: HTMLElement, options: FrameportOptions): void => {\n if (\n !targetElement ||\n !options ||\n (options && Object.keys(options).length === 0)\n )\n return;\n\n const { html, viewports, templateElement } = options;\n\n if (!html || html === '') return;\n\n addStyles(templateElement as HTMLElement, HIDE_TEMPLATE_STYLE);\n\n if (viewports) {\n generateViewports(targetElement, options);\n } else {\n generate(targetElement, options);\n }\n};\n\nexport default dom;\n","import { FrameportOptions } from '../types';\nimport { create } from '../utils/create';\n\n/**\n * Generate multiple iframe elements for different viewports and append them to a target element.\n *\n * @param {HTMLElement} target - The target HTML element to insert iframes after.\n * @param {FrameportOptions} options - The options for generating the iframes.\n * @returns {void}\n */\nexport const generateViewports = (\n target: HTMLElement,\n options: FrameportOptions\n): void => {\n const { viewports } = options;\n\n if (!viewports || viewports === '') return;\n\n let screens: string[] = [];\n\n if (viewports.includes(',')) screens = [...screens, ...viewports.split(',')];\n else screens.push(viewports);\n\n for (const viewPort of screens) {\n const values = viewPort.split('x');\n const [width, height] = values;\n const iframeElement = create({ ...options, height, width });\n\n target.insertAdjacentElement('afterend', iframeElement);\n }\n};\n","import { FrameportOptions } from '../types';\nimport { create } from '../utils/create';\n\n/**\n * Generate an iframe with the given options and append it to a target element.\n *\n * @param {HTMLElement} targetElement - The target HTML element to append the iframe to.\n * @param {FrameportOptions} options - The options for generating the iframe.\n * @returns {void}\n */\nexport const generate = (\n targetElement: HTMLElement,\n options: FrameportOptions\n): void => {\n const { width } = options;\n\n if (!width) return;\n\n const iframeElement = create(options);\n\n targetElement.append(iframeElement);\n};\n","import { DEFAULT_HEADERS } from '../constants';\n\n/**\n * Get headers for the iframe generated\n *\n * @param {string|string[]|null|undefined} rdeHeaders - The custom headers to include.\n * @returns {string[]} - An array of headers, including default and custom headers.\n */\nexport const getHeaders = (\n rdeHeaders: string | string[] | null | undefined\n): string[] => {\n let headers: string[] = [...DEFAULT_HEADERS];\n\n if (rdeHeaders) {\n if (Array.isArray(rdeHeaders)) {\n headers = [...headers, ...rdeHeaders].map((h) => h.trim());\n } else if (rdeHeaders.includes(',')) {\n headers = [...headers, ...rdeHeaders.split(',')].map((h) => h.trim());\n } else if (rdeHeaders !== '') {\n headers.push(rdeHeaders.trim());\n }\n }\n\n return headers;\n};\n","/* eslint no-console:0 */\nimport dom from '../features/dom';\nimport { FrameportFunctionType } from '../types';\nimport { getHeaders } from '../utils/headers';\n\n/**\n * A function to initialize frameport when the DOM is ready.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // domReady(myRDE);\n * ```\n */\nexport const domReady = (frameport: FrameportFunctionType): void => {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n frameport();\n });\n } else {\n // `DOMContentLoaded` already fired\n frameport();\n }\n};\n\n/**\n * A function to initialize lazy frameport functionality.\n *\n * @example\n * ```ts\n * // Usage example:\n * // lazy();\n * ```\n */\nexport const lazy = (): void => {\n const frameportObserverTarget = new IntersectionObserver((els, observer) => {\n els.forEach((el: IntersectionObserverEntry) => {\n if (el.intersectionRatio > 0) {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports\n }\n } = el.target as HTMLElement;\n\n let html = el.target.innerHTML;\n let templateElementToUse = el.target as HTMLElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports\n };\n\n dom(el.target as HTMLElement, options);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-frameport]').forEach((el) => {\n frameportObserverTarget.observe(el);\n });\n};\n\n/**\n * A function to manually activate frameport.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // manual(myRDE);\n * ```\n */\nexport const manual = (frameport: FrameportFunctionType): void => {\n window.frameport = frameport;\n};\n\n/**\n * A function to activate frameport based on script attributes.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // activate(myRDE);\n * ```\n */\nexport const activate = (frameport: FrameportFunctionType): void => {\n const script = document.currentScript;\n\n if (script) {\n const frameportScriptSrc = script.getAttribute('src');\n\n if (frameportScriptSrc && frameportScriptSrc.includes('frameport.js')) {\n if (script.hasAttribute('data-manual')) {\n manual(frameport);\n } else if (script.hasAttribute('data-instant')) {\n frameport();\n } else if (script.hasAttribute('data-dom')) {\n domReady(frameport);\n } else if (script.hasAttribute('data-lazy')) {\n lazy();\n } else {\n domReady(frameport);\n }\n }\n }\n};\n","/* eslint-disable import/no-unused-modules */\nimport { domReady, lazy, manual, activate } from './config/browser';\nimport dom from './features/dom';\nimport { getHeaders } from './utils/headers';\n\nexport const modes = {\n domReady,\n lazy,\n manual,\n activate\n};\n\nconst frameport = () => {\n document\n .querySelectorAll('[data-frameport-iframe]')\n .forEach((iframe) => iframe.remove());\n\n const elsToBeTransformedTemplate =\n document.querySelectorAll('[data-frameport]');\n\n elsToBeTransformedTemplate.forEach((targetElement: HTMLElement) => {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports\n }\n } = targetElement;\n\n let html = targetElement.innerHTML;\n let templateElementToUse = targetElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports\n };\n\n dom(targetElement, options);\n });\n};\n\nexport default frameport;\n\nactivate(frameport);\n"],"names":["getSource","options","style","css","code","javascript","html","headers","window","location","protocol","host","trim","getCSS","getJavaScript","getCode","getStyle","join","getGeneratedPageURL","type","blob","Blob","URL","createObjectURL","getBlobURL","add","async","el","styles","Array","isArray","length","Object","keys","constructor","Promise","requestAnimationFrame","forEach","key","value","create","className","height","width","url","iframeElement","document","createElement","iframeStyle","src","setAttribute","classList","addStyles","HIDE_TEMPLATE_STYLE","clip","margin","overflow","position","DEFAULT_HEADERS","dom","targetElement","viewports","templateElement","target","screens","includes","split","push","viewPort","values","insertAdjacentElement","generateViewports","append","generate","getHeaders","rdeHeaders","map","h","domReady","frameport","readyState","addEventListener","lazy","frameportObserverTarget","IntersectionObserver","els","observer","intersectionRatio","dataset","frameportTemplate","templateSelector","frameportVh","frameportVw","frameportCss","frameportStyle","frameportCode","frameportJs","frameportClass","frameportHeaders","frameportViewports","innerHTML","templateElementToUse","querySelector","unobserve","querySelectorAll","observe","manual","activate","script","currentScript","frameportScriptSrc","getAttribute","hasAttribute","modes","iframe","remove"],"mappings":"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"}
package/package.json CHANGED
@@ -1,28 +1,37 @@
1
1
  {
2
2
  "name": "@phun-ky/frameport",
3
- "version": "1.2.3",
3
+ "version": "2.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "description": "Create responsive documentation examples on the fly",
8
- "main": "frameport.js",
9
- "types": "frameport.d.ts",
8
+ "main": "dist/frameport.js",
9
+ "module": "dist/frameport.esm.js",
10
+ "types": "dist/frameport.d.ts",
11
+ "type": "module",
10
12
  "scripts": {
11
- "test": "echo \"Error: no test specified\" && exit 1",
13
+ "test": "glob -c \"node --import tsx --import global-jsdom/register --test --no-warnings\" \"./src/**/__tests__/**/*.[jt]s\"",
14
+ "pretest-ci": "rm -rf coverage && mkdir -p coverage",
15
+ "test-ci": "glob -c \"node --import tsx --import global-jsdom/register --test --no-warnings --experimental-test-coverage --test-reporter=cobertura --test-reporter-destination=coverage/cobertura-coverage.xml --test-reporter=spec --test-reporter-destination=stdout\" \"./src/**/__tests__/**/*.[jt]s\"",
12
16
  "rollup": "rollup -c",
13
17
  "prerollup:dev": "npm run clean",
14
18
  "rollup:dev": "rollup -c -w",
15
- "clean": "rm -rf dist/ dts/ ./frameport.js",
19
+ "clean": "rm -rf dist dts",
16
20
  "build": "npm run clean && npm run rollup",
17
- "dev": "npx browser-sync start -s --files \"dev/*.html\" \"*.css\" --index \"dev/index.html\" --serveStatic \"/dev/*\"",
21
+ "dev": "npx browser-sync start --server 'dev' --files 'dist' --ss 'dist'",
18
22
  "docs:gen": "node ./node_modules/.bin/typedoc --entryPoints src --entryPointStrategy expand --gitRevision main --githubPages false --plugin typedoc-plugin-markdown --tsconfig tsconfig.json --hideInPageTOC --out api --readme none",
23
+ "style:lint": "./node_modules/.bin/eslint -c ./.eslintrc --max-warnings=0 src --ignore-path .gitignore ",
24
+ "style:format": "prettier-eslint --config .prettierrc --eslint-config-path $PWD/.eslintrc --list-different --write \"./src/**/*.ts\"",
25
+ "style:code": "npx putout src",
19
26
  "commit": "npx git-cz",
20
27
  "release": "release-it"
21
28
  },
22
29
  "files": [
23
- "/frameport.js",
24
- "/frameport.js.map",
25
- "/frameport.d.ts"
30
+ "/dist/frameport.esm.js",
31
+ "/dist/frameport.esm.js.map",
32
+ "/dist/frameport.js",
33
+ "/dist/frameport.js.map",
34
+ "/dist/frameport.d.ts"
26
35
  ],
27
36
  "repository": {
28
37
  "type": "git",
@@ -41,6 +50,9 @@
41
50
  "html",
42
51
  "viewport",
43
52
  "frame",
53
+ "iframes",
54
+ "iframe",
55
+ "component",
44
56
  "frameport"
45
57
  ],
46
58
  "author": "Alexander Vassbotn Røyne-Helgesen <alexander+frameport@phun-ky.net>",
@@ -50,43 +62,52 @@
50
62
  },
51
63
  "homepage": "https://github.com/phun-ky/frameport#readme",
52
64
  "devDependencies": {
53
- "@release-it/conventional-changelog": "^7.0.1",
54
- "@rollup/plugin-commonjs": "^17.1.0",
55
- "@rollup/plugin-node-resolve": "^11.2.0",
56
- "@typescript-eslint/eslint-plugin": "^5.7.0",
57
- "@typescript-eslint/parser": "^5.7.0",
58
- "esbuild-jest": "^0.5.0",
59
- "eslint": "^7.32.0",
60
- "eslint-config-airbnb": "^18.2.1",
61
- "eslint-config-prettier": "^8.3.0",
62
- "eslint-plugin-compat": "^3.13.0",
63
- "eslint-plugin-import": "^2.24.2",
64
- "eslint-plugin-prettier": "^4.0.0",
65
- "eslint-plugin-react": "^7.23.2",
66
- "eslint-plugin-react-hooks": "^4.2.0",
65
+ "@release-it/conventional-changelog": "^8.0.1",
66
+ "@rollup/plugin-node-resolve": "^15.2.3",
67
+ "@rollup/plugin-terser": "^0.4.4",
68
+ "@testing-library/dom": "^9.3.4",
69
+ "@testing-library/jest-dom": "^6.4.2",
70
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
71
+ "@typescript-eslint/parser": "^5.0.1",
72
+ "cobertura": "^1.0.1",
73
+ "eslint": "^8.56.0",
74
+ "eslint-config-prettier": "^9.1.0",
75
+ "eslint-import-resolver-typescript": "3.6.1",
76
+ "eslint-plugin-compat": "^4.2.0",
77
+ "eslint-plugin-import": "^2.29.1",
78
+ "eslint-plugin-prettier": "^5.1.3",
67
79
  "git-cz": "^4.9.0",
68
- "network-information-types": "^0.1.1",
69
- "prettier": "^2.4.1",
70
- "prettier-eslint": "^13.0.0",
71
- "release-it": "^16.1.5",
72
- "rollup": "^2.39.0",
73
- "rollup-plugin-dts": "^4.0.1",
74
- "rollup-plugin-terser": "^7.0.2",
75
- "rollup-plugin-typescript2": "^0.35.0",
76
- "ts-jest": "^29.1.1",
80
+ "glob": "^10.3.10",
81
+ "global-jsdom": "^24.0.0",
82
+ "jsdom": "^24.0.0",
83
+ "prettier": "^3.2.5",
84
+ "prettier-eslint": "^16.3.0",
85
+ "prettier-eslint-cli": "^8.0.1",
86
+ "putout": "^35.1.0",
87
+ "quibble": "^0.9.1",
88
+ "release-it": "^17.1.1",
89
+ "rollup": "^4.12.0",
90
+ "rollup-plugin-dts": "^6.1.0",
91
+ "rollup-plugin-typescript2": "^0.36.0",
92
+ "stylus": "^0.62.0",
77
93
  "ts-node": "^10.9.1",
78
94
  "tslib": "^2.3.1",
79
- "typedoc": "^0.25.2",
95
+ "tsx": "^4.7.1",
96
+ "typedoc": "^0.25.8",
80
97
  "typedoc-plugin-frontmatter": "^0.0.2",
81
- "typedoc-plugin-markdown": "^3.15.3",
82
- "typedoc-plugin-mdn-links": "^3.0.3",
98
+ "typedoc-plugin-markdown": "^3.17.1",
99
+ "typedoc-plugin-mdn-links": "^3.1.16",
83
100
  "typedoc-plugin-no-inherit": "^1.4.0",
84
- "typedoc-plugin-rename-defaults": "^0.6.5",
85
- "typescript": "^4.5.4"
101
+ "typedoc-plugin-rename-defaults": "^0.7.0",
102
+ "typescript": "^5.0.0"
86
103
  },
87
104
  "config": {
88
105
  "commitizen": {
89
106
  "path": "./node_modules/git-cz"
90
107
  }
108
+ },
109
+ "engines": {
110
+ "node": ">=20.11.1",
111
+ "npm": ">=10.2.4"
91
112
  }
92
113
  }
package/frameport.js DELETED
@@ -1,2 +0,0 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).frameport={})}(this,(function(e){"use strict";const t=e=>{let{html:t,style:r,css:o,code:a,javascript:n,headers:s=[]}=e;return o=(e=>e?`<link rel="stylesheet" type="text/css" href="${window.location.protocol}//${window.location.host}${e}" />`:"")(o),n=(e=>e?`<script src="${window.location.protocol}//${window.location.host}${e}"><\/script>`:"")(n),a=(e=>e?`<script>${e}<\/script>`:"")(a),r=(e=>e?`<style type="text/css">\n ${e}\n </style>`:"")(r),`<!DOCTYPE html><html>\n <head>\n ${s.join("\n")}\n ${r}\n ${o}\n </head>\n <body>\n ${t||""}\n ${n}\n ${a}\n </body>\n</html>`},r=e=>((e,t)=>{const r=new Blob([e],{type:t});return URL.createObjectURL(r)})(t(e),"text/html"),o=async(e,t)=>{!e||!t||"string"==typeof t||"number"==typeof t||"boolean"==typeof t||Array.isArray(t)&&0===t.length||0===Object.keys(t).length&&t.constructor===Object||(await new Promise(requestAnimationFrame),Array.isArray(t)?t.forEach((t=>e.style[t.key]=t.value)):Object.keys(t).forEach((r=>e.style[r]=t[r])))},a=e=>{const{className:t,height:a,width:n}=e,s=r(e),i=document.createElement("iframe"),c={};return i.src=s,i.setAttribute("data-rde-iframe",""),t&&""!==t?i.classList.add(t):c.border="none",c.width=`${n}px`,a&&(c.height=`${a}px`),o(i,c),i},n={clip:"rect(1px, 1px, 1px, 1px)",height:"1px",margin:"0",overflow:"hidden",position:"absolute",width:"1px"},s=['<meta charset="utf-8" />','<meta name="robots" content="none" />','<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />','<meta name="viewport" content="width=device-width, initial-scale=1" />'],i=(e,t)=>{if(!e||!t||t&&0===Object.keys(t).length)return;const{html:r,viewports:s,templateElement:i}=t;r&&""!==r&&(o(i,n),s?((e,t)=>{const{viewports:r}=t;if(!r||""===r)return;let o=[];-1!==r.indexOf(",")?o=[...o,...r.split(",")]:o.push(r),o.forEach((r=>{const o=r.split("x"),n=o[0],s=o[1],i=a({...t,height:s,width:n});e.insertAdjacentElement("afterend",i)}))})(e,t):((e,t)=>{const{width:r}=t;if(!r)return;const o=a(t);e.append(o)})(e,t))},c=e=>{let t=[...s];return e&&(Array.isArray(e)?t=[...t,...e]:-1!==e.indexOf(",")?t=[...t,...e.split(",")]:""!==e&&t.push(e)),t},l=e=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{e()})):e()},d=()=>{const e=new IntersectionObserver(((e,t)=>{e.forEach((e=>{if(e.intersectionRatio>0){const{dataset:{frameportTemplate:r,frameportVh:o,frameportVw:a,frameportCss:n,frameportStyle:s,frameportCode:l,frameportJs:d,frameportClass:p,frameportHeaders:m,frameportViewports:f}}=e.target;let h=e.target.innerHTML,u=e.target;if(r){const e=document.querySelector(r);e&&(h=e.innerHTML,u=e)}const y={templateSelector:r,templateElement:u,height:o,width:a,html:h,css:n,style:s,code:l,javascript:d,className:p,headers:c(m),viewports:f};i(e.target,y),t.unobserve(e.target)}}))}));document.querySelectorAll("[data-frameport]").forEach((t=>{e.observe(t)}))},p=e=>{window.frameport=e},m=e=>{const t=document.currentScript;if(t){const r=t.getAttribute("src");r&&-1!==r.indexOf("frameport.js")&&(t.hasAttribute("data-manual")?p(e):t.hasAttribute("data-instant")?e():t.hasAttribute("data-dom")?l(e):t.hasAttribute("data-lazy")?d():l(e))}},f={domReady:l,lazy:d,manual:p,activate:m},h=()=>{document.querySelectorAll("[data-frameport-iframe]").forEach((e=>e.remove()));document.querySelectorAll("[data-frameport]").forEach((e=>{const{dataset:{frameportTemplate:t,frameportVh:r,frameportVw:o,frameportCss:a,frameportStyle:n,frameportCode:s,frameportJs:l,frameportClass:d,frameportHeaders:p,frameportViewports:m}}=e;let f=e.innerHTML,h=e;if(t){const e=document.querySelector(t);e&&(f=e.innerHTML,h=e)}const u={templateSelector:t,templateElement:h,height:r,width:o,html:f,css:a,style:n,code:s,javascript:l,className:d,headers:c(p),viewports:m};i(e,u)}))};m(h),e.default=h,e.modes=f,Object.defineProperty(e,"__esModule",{value:!0})}));
2
- //# sourceMappingURL=frameport.js.map
package/frameport.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"frameport.js","sources":["src/utils/iframe.ts","src/utils/source.ts","src/utils/css.ts","src/utils/js.ts","src/utils/code.ts","src/utils/style.ts","src/utils/page.ts","src/utils/blob.ts","src/utils/styles.ts","src/utils/wait.ts","src/utils/create.ts","src/utils/constants.ts","src/features/dom.ts","src/config/generate-viewports.ts","src/config/generate.ts","src/utils/headers.ts","src/config/browser.ts","src/main.ts"],"sourcesContent":["/**\n * Create and return an iframe element.\n *\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const createIframe = (): HTMLIFrameElement => document.createElement('iframe');\n","import { getCode } from './code';\nimport { getCSS } from './css';\nimport { getJavaScript } from './js';\nimport { FrameportOptions } from '../types';\nimport { getStyle } from './style';\n\n/**\n * Generate the source code for an HTML page based on the provided options.\n *\n * @param {FrameportOptions} options - The options for generating the HTML page source.\n * @returns {string} - The generated HTML source code as a string.\n */\nexport const getSource = (options: FrameportOptions): string => {\n let { html, style, css, code, javascript, headers = [] } = options;\n\n css = getCSS(css);\n javascript = getJavaScript(javascript);\n code = getCode(code);\n style = getStyle(style);\n\n return `<!DOCTYPE html><html>\n <head>\n ${headers.join('\\n')}\n ${style}\n ${css}\n </head>\n <body>\n ${html || ''}\n ${javascript}\n ${code}\n </body>\n</html>`;\n};\n","/**\n * Generate a CSS link tag based on the provided URL.\n *\n * @param {string | undefined} css - The URL of the CSS file.\n * @returns {string} - A CSS link tag.\n */\nexport const getCSS = (css: string | undefined): string => {\n if (css) {\n return `<link rel=\"stylesheet\" type=\"text/css\" href=\"${window.location.protocol}//${window.location.host}${css}\" />`;\n }\n return '';\n};\n","/**\n * Generate a script tag for the specified JavaScript file.\n *\n * @param {string | undefined} javascript - The path to the JavaScript file.\n * @returns {string} - The generated script tag or an empty string if no JavaScript path is provided.\n */\nexport const getJavaScript = (javascript: string | undefined): string => {\n if (javascript) {\n return `<script src=\"${window.location.protocol}//${window.location.host}${javascript}\"></script>`;\n }\n return '';\n};\n","/**\n * Get a script element containing the provided code if available.\n *\n * @param {string | undefined} code - The code to include in the script element.\n * @returns {string} - The script element or an empty string if code is not available.\n */\nexport const getCode = (code: string | undefined): string => {\n if (code) {\n return `<script>${code}</script>`;\n }\n return '';\n};\n","/**\n * Generate a style element based on the provided CSS styles.\n *\n * @param {string | undefined} style - The CSS styles to include in the style element.\n * @returns {string} - The style element as a string or an empty string if no styles are provided.\n */\nexport const getStyle = (style: string | undefined): string => {\n if (style) {\n return `<style type=\"text/css\">\n ${style}\n </style>`;\n }\n return '';\n};\n","import { getBlobURL } from \"./blob\";\nimport { getSource } from \"./source\";\n\n/**\n * Get the URL of a generated HTML page based on the provided options.\n *\n * @param {object} options - The options for generating the HTML page.\n * @returns {string} - The URL of the generated HTML page as a Blob URL.\n */\nexport const getGeneratedPageURL = (options) => {\n const source = getSource(options);\n return getBlobURL(source, 'text/html');\n};\n","/**\n * Generates a Blob URL from HTML content with the specified MIME type.\n *\n * @param {string} html - The HTML content to create a Blob from.\n * @param {string} type - The MIME type of the Blob (e.g., 'text/html', 'image/jpeg').\n * @returns {string} - The generated Blob URL.\n */\nexport const getBlobURL = (html: string, type: string): string => {\n const blob = new Blob([html], { type });\n return URL.createObjectURL(blob);\n};\n","/* eslint no-console:0 */\n'use strict';\nimport { waitForFrame } from './wait';\n\n/**\n * Adds CSS styles to an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to apply styles to.\n * @param {object | Array<{ key: string; value: string }>} styles - An object or an array of objects containing CSS styles to apply.\n * @returns {Promise<void>} - A Promise that resolves after styles are applied.\n *\n * @example\n * ```ts\n * // Apply styles as an object\n * const element = document.getElementById('my-element');\n * await add(element, { color: 'red', fontSize: '16px' });\n *\n * // Apply styles as an array of objects\n * const styles = [\n * { key: 'color', value: 'blue' },\n * { key: 'backgroundColor', value: 'yellow' }\n * ];\n * await add(element, styles);\n * ```\n */\nexport const add = async (\n el: HTMLElement,\n styles: object | Array<{ key: string; value: string }>\n): Promise<void> => {\n if (\n !el ||\n !styles ||\n typeof styles === 'string' ||\n typeof styles === 'number' ||\n typeof styles === 'boolean' ||\n (Array.isArray(styles) && styles.length === 0) ||\n (Object.keys(styles).length === 0 && styles.constructor === Object)\n ) {\n return;\n }\n\n await waitForFrame();\n\n if (Array.isArray(styles)) {\n styles.forEach(\n (style: { key: string; value: string }) =>\n (el.style[style.key] = style.value)\n );\n } else {\n Object.keys(styles).forEach((key) => (el.style[key] = styles[key]));\n }\n};\n\n/**\n * Gets the computed CSS styles of an HTMLElement.\n *\n * @param {HTMLElement} el - The HTMLElement to get computed styles from.\n * @returns {Promise<CSSStyleDeclaration>} - A Promise that resolves with the computed CSS styles.\n *\n * @example\n * ```ts\n * // Get computed styles of an element\n * const element = document.getElementById('my-element');\n * const computedStyles = await get(element);\n * console.log(computedStyles.color); // Logs the color property value\n * ```\n */\nexport const get = async (el: HTMLElement): Promise<CSSStyleDeclaration> => {\n await waitForFrame();\n\n return getComputedStyle(el, null);\n};\n","/**\n * Waits for the specified amount of time in milliseconds.\n *\n * @param {number} ms - The number of milliseconds to wait.\n * @returns {Promise<void>} - A Promise that resolves after the specified time.\n *\n * @example\n * ```ts\n * // Wait for 1 second (1000 milliseconds)\n * await waitFor(1000);\n * ```\n */\nexport const waitFor = (ms: number): Promise<void> =>\n new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/**\n * Waits for the next animation frame using requestAnimationFrame.\n *\n * @returns {Promise<number>} - A Promise that resolves with the timestamp of the next animation frame.\n *\n * @example\n * ```ts\n * // Wait for the next animation frame and get the rect\n * await waitForFrame();\n * const rect = el.getBoundingClientRect();\n * // Wait for the next animation frame and get the timestamp\n * const timestamp = await waitForFrame();\n * ```\n */\nexport const waitForFrame = (): Promise<number> =>\n new Promise<number>(requestAnimationFrame);\n","import { FrameportOptions } from 'types';\nimport { createIframe } from 'utils/iframe';\nimport { getGeneratedPageURL } from 'utils/page';\nimport { add as addStyles } from 'utils/styles';\n\n/**\n * Create an iframe element with specified options and styles.\n *\n * @param {FrameportOptions} options - The options for creating the iframe.\n * @returns {HTMLIFrameElement} - The created iframe element.\n */\nexport const create = (\n options: FrameportOptions\n): HTMLIFrameElement => {\n const { className, height, width } = options;\n const url = getGeneratedPageURL(options);\n const iframeElement = createIframe();\n const iframeStyle = {};\n\n iframeElement.src = url;\n iframeElement.setAttribute('data-rde-iframe', '');\n\n if (!className || className === '') {\n iframeStyle['border'] = 'none';\n } else {\n iframeElement.classList.add(className);\n }\n\n iframeStyle['width'] = `${width}px`;\n\n if (height) {\n iframeStyle['height'] = `${height}px`;\n }\n\n addStyles(iframeElement, iframeStyle);\n\n return iframeElement;\n};\n","/**\n * Style object for hiding an element in the HTML.\n *\n * @type {{ clip: string, height: string, margin: string, overflow: string, position: string, width: string }}\n */\nexport const HIDE_TEMPLATE_STYLE: { clip: string; height: string; margin: string; overflow: string; position: string; width: string; } = {\n clip: 'rect(1px, 1px, 1px, 1px)',\n height: '1px',\n margin: '0',\n overflow: 'hidden',\n position: 'absolute',\n width: '1px'\n};\n\n/**\n * Default meta headers for an HTML document.\n *\n * @type {string[]}\n */\nexport const DEFAULT_HEADERS: string[] = [\n '<meta charset=\"utf-8\" />',\n '<meta name=\"robots\" content=\"none\" />',\n '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />'\n];\n","import { generate } from 'config/generate';\nimport { generateViewports } from 'config/generate-viewports';\nimport { FrameportOptions } from 'types';\nimport { HIDE_TEMPLATE_STYLE } from 'utils/constants';\nimport { add as addStyles } from 'utils/styles';\n\n/**\n * Generate iframes into the DOM, possibly generating viewports.\n *\n * @param {HTMLElement} targetElement - The target HTML element.\n * @param {FrameportOptions} options - The options for the iframe.\n * @returns {void}\n */\nconst dom = (\n targetElement: HTMLElement,\n options: FrameportOptions\n): void => {\n if (\n !targetElement ||\n !options ||\n (options && Object.keys(options).length === 0)\n )\n return;\n\n const { html, viewports, templateElement } = options;\n\n if (!html || html === '') return;\n\n addStyles(templateElement as HTMLElement, HIDE_TEMPLATE_STYLE);\n\n if (viewports) {\n generateViewports(targetElement, options);\n } else {\n generate(targetElement, options);\n }\n};\n\nexport default dom;\n","import { FrameportOptions } from 'types';\nimport { create } from 'utils/create';\n\n/**\n * Generate multiple iframe elements for different viewports and append them to a target element.\n *\n * @param {HTMLElement} target - The target HTML element to insert iframes after.\n * @param {FrameportOptions} options - The options for generating the iframes.\n * @returns {void}\n */\nexport const generateViewports = (\n target: HTMLElement,\n options: FrameportOptions\n): void => {\n const { viewports } = options;\n\n if (!viewports || viewports === '') return;\n\n let screens: string[] = [];\n\n if (viewports.indexOf(',') !== -1) {\n screens = [...screens, ...viewports.split(',')];\n } else {\n screens.push(viewports);\n }\n\n screens.forEach((viewPort: string) => {\n const values = viewPort.split('x');\n const width = values[0];\n const height = values[1];\n\n const iframeElement = create({ ...options, height, width });\n\n target.insertAdjacentElement('afterend', iframeElement);\n });\n};\n","import { FrameportOptions } from 'types';\nimport { create } from 'utils/create';\n\n/**\n * Generate an iframe with the given options and append it to a target element.\n *\n * @param {HTMLElement} targetElement - The target HTML element to append the iframe to.\n * @param {FrameportOptions} options - The options for generating the iframe.\n * @returns {void}\n */\nexport const generate = (\n targetElement: HTMLElement,\n options: FrameportOptions\n): void => {\n const { width } = options;\n\n if (!width) return;\n\n const iframeElement = create(options);\n\n targetElement.append(iframeElement);\n};\n","import { DEFAULT_HEADERS } from \"./constants\";\n\n/**\n * Get headers for the iframe generated\n *\n * @param {string|string[]|null|undefined} rdeHeaders - The custom headers to include.\n * @returns {string[]} - An array of headers, including default and custom headers.\n */\nexport const getHeaders = (rdeHeaders: string | string[] | null | undefined): string[] => {\n let headers: string[] = [...DEFAULT_HEADERS];\n\n if (rdeHeaders) {\n if (Array.isArray(rdeHeaders)) {\n headers = [...headers, ...rdeHeaders];\n } else if (rdeHeaders.indexOf(',') !== -1) {\n headers = [...headers, ...rdeHeaders.split(',')];\n } else if (rdeHeaders !== '') {\n headers.push(rdeHeaders);\n }\n }\n\n return headers;\n};\n","/* eslint no-console:0 */\n'use strict';\n\nimport { FrameportFunctionType } from 'types';\nimport dom from 'features/dom';\nimport { getHeaders } from 'utils/headers';\n\n/**\n * A function to initialize frameport when the DOM is ready.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // domReady(myRDE);\n * ```\n */\nexport const domReady = (\n frameport: FrameportFunctionType\n): void => {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n frameport();\n });\n } else {\n // `DOMContentLoaded` already fired\n frameport();\n }\n};\n\n/**\n * A function to initialize lazy frameport functionality.\n *\n * @example\n * ```ts\n * // Usage example:\n * // lazy();\n * ```\n */\nexport const lazy = (): void => {\n const frameportObserverTarget = new IntersectionObserver((els, observer) => {\n els.forEach((el: IntersectionObserverEntry) => {\n if (el.intersectionRatio > 0) {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports,\n },\n } = el.target as HTMLElement;\n\n let html = el.target.innerHTML;\n let templateElementToUse = el.target as HTMLElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports,\n };\n dom(el.target as HTMLElement, options);\n observer.unobserve(el.target);\n }\n });\n });\n\n document.querySelectorAll('[data-frameport]').forEach((el) => {\n frameportObserverTarget.observe(el);\n });\n};\n\n/**\n * A function to manually activate frameport.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // manual(myRDE);\n * ```\n */\nexport const manual = (\n frameport: FrameportFunctionType\n): void => {\n window.frameport = frameport;\n};\n\n/**\n * A function to activate frameport based on script attributes.\n *\n * @param {FrameportFunctionType} frameport - The frameport function to execute.\n *\n * @example\n * ```ts\n * // Usage example:\n * // activate(myRDE);\n * ```\n */\nexport const activate = (\n frameport: FrameportFunctionType\n): void => {\n const script = document.currentScript;\n\n if (script) {\n const frameportScriptSrc = script.getAttribute('src');\n\n if (frameportScriptSrc && frameportScriptSrc.indexOf('frameport.js') !== -1) {\n if (script.hasAttribute('data-manual')) {\n manual(frameport);\n } else if (script.hasAttribute('data-instant')) {\n frameport();\n } else if (script.hasAttribute('data-dom')) {\n domReady(frameport);\n } else if (script.hasAttribute('data-lazy')) {\n lazy();\n } else {\n domReady(frameport);\n }\n }\n }\n};\n","import { domReady, lazy, manual, activate } from 'config/browser';\nimport dom from 'features/dom';\nimport { getHeaders } from 'utils/headers';\n\nexport const modes = {\n domReady,\n lazy,\n manual,\n activate,\n};\n\nconst frameport = () => {\n document\n .querySelectorAll('[data-frameport-iframe]')\n .forEach((iframe) => iframe.remove());\n\n const elsToBeTransformedTemplate = document.querySelectorAll('[data-frameport]');\n\n elsToBeTransformedTemplate.forEach((targetElement: HTMLElement) => {\n const {\n dataset: {\n frameportTemplate: templateSelector,\n frameportVh: height,\n frameportVw: width,\n frameportCss: css,\n frameportStyle: style,\n frameportCode: code,\n frameportJs: javascript,\n frameportClass: className,\n frameportHeaders: headers,\n frameportViewports: viewports,\n },\n } = targetElement;\n\n let html = targetElement.innerHTML;\n let templateElementToUse = targetElement;\n\n if (templateSelector) {\n const templateElement = document.querySelector(templateSelector);\n\n if (templateElement) {\n html = templateElement.innerHTML;\n templateElementToUse = templateElement as HTMLElement;\n }\n }\n\n const options = {\n templateSelector,\n templateElement: templateElementToUse,\n height,\n width,\n html,\n css,\n style,\n code,\n javascript,\n className,\n headers: getHeaders(headers),\n viewports,\n };\n\n dom(targetElement, options);\n });\n};\n\nexport default frameport;\n\nactivate(frameport);\n"],"names":["getSource","options","html","style","css","code","javascript","headers","window","location","protocol","host","getCSS","getJavaScript","getCode","getStyle","join","getGeneratedPageURL","type","blob","Blob","URL","createObjectURL","getBlobURL","add","async","el","styles","Array","isArray","length","Object","keys","constructor","Promise","requestAnimationFrame","forEach","key","value","create","className","height","width","url","iframeElement","document","createElement","iframeStyle","src","setAttribute","classList","addStyles","HIDE_TEMPLATE_STYLE","clip","margin","overflow","position","DEFAULT_HEADERS","dom","targetElement","viewports","templateElement","target","screens","indexOf","split","push","viewPort","values","insertAdjacentElement","generateViewports","append","generate","getHeaders","rdeHeaders","domReady","frameport","readyState","addEventListener","lazy","frameportObserverTarget","IntersectionObserver","els","observer","intersectionRatio","dataset","frameportTemplate","templateSelector","frameportVh","frameportVw","frameportCss","frameportStyle","frameportCode","frameportJs","frameportClass","frameportHeaders","frameportViewports","innerHTML","templateElementToUse","querySelector","unobserve","querySelectorAll","observe","manual","activate","script","currentScript","frameportScriptSrc","getAttribute","hasAttribute","modes","iframe","remove"],"mappings":"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"}