Asrı - Modern Flexibility, Client-side - [NEW v0.0.9]

Asrı

A super high level professional-flow Framework Boilerplate

It allows for you to streamline your code without the complications of old-school, spaghetti frameworks, barely stitched together by big coorps!

Live Examples of high end pages:

3 Likes

Did you make this framework?
What language is this in?

1 Like

Yes, Spcfork did.

JS

1 Like

See here for Latest Asri content.
Asrı - Official Website

1 Like

That is, indeed, what the Showcase category is for.

1 Like

Asri now has a standard lib, you can now selectively import these module sets in the 3 groups.


(These are the bundles that are available to import in mass to begin with)

image


These are meant to be a replacement for the underwhelming JQuery V4 release
Hopefully these are decent enough to make up for it.

USAGE

You can use these new features by importing the global load...lib Functions added above.

The modules included are injected into the Global Scope.

Put this in an await somewhere before load, preferably in Preload.


Get the latest potentially unstable BETA release at the git
v0.0.5 - The Libs Update
GITHUB


Do note that Replit is suuuper cool, and that this is a super cool trick too!!

Hey @Spcfork!

Really interesting! What do all of the Module Sets do and what are their use cases?

1 Like

I will write JSDOCs and post each image here,
this will probably take ~20 mins.

1 Like

SUBM Standard


Debounce

image


Deep Clone

image


Default

image


Format Date

image


Get Language

image


Is Darkmode?

image


Is Mobile Device?


Levenshtein Distance (String Matching Precentile)


Merge Objects

image


Random In Range

image


Retry


Scroll To

image


Throttle


Better Type

image


UUID Reimplemented in JS code.

image


Susha Dropdown


image


Array Mod(ule)


Bin Search

image


Chunk Array

image


Flatten Array


Shuffle Array

image


Unique Array

image


3rd Party


AdviceSlipAPI

image
image
image
image


Books


Chuck Norris


Lorem Gen


QR Code Generator


Random User Gen

4 Likes

v0.0.6 - The Redirect Update

Now you can create redirect pages with the /_Asri Templates/redirect.html & /_Asri Templates/redirect.js template set.


image

Or you could have it top-level with the HTML entry point, rather than in the /app/redirects dir.

image


The redirect.json follows this structure.

image

When used with the /src/redirect.js script, these will automatically import this data, and use it in the redirect process.

You could also adjust this to whatever your needs are, these are prototypes at the moment as well.


This clientware is great if you want to pass the Redirection handling to the client, rather than building an API which has to handle Redirect hooks.

It does this by following the path as folders within the current redirection scope folder (top level, or within /app/redirects/).


Eventually, there may even be a better structure implemented, maybe even a Replit Plugin for interfacing with the Asri wAPI.


Be on the lookout for ChubML Asri Router


Get the latest potentially unstable BETA release at the git
v0.0.6 - The Redirect Update

3 Likes

image

image


Soon, we will have cross ChubML-and-Susha support, so now you have two crazy useful HTML interops at once!!

2 Likes

v0.0.7 - The ChubML to Susha Update

Now you can use ChubML inside of your Susha Apps.

Asri allows for the Susha SPA Router to accept ChubML, along with the ability to use ChubML elsewhere within your apps, as HTML, or XML.

Watch soon for a potential ChubXMLReq/Fetch implementation !!


image
image



Get the latest potentially unstable BETA release at the git
v0.0.7 - The ChubML to Susha Update

3 Likes

v0.0.8 - The Susha to JSX Update



I’ve decided to implement JSX-React-Like Object generators.
You can now generate these objects from Susha elements (which means Chub to JSX is now possible)


image


This object format is the internal parsed result of JSX post-babel code.

Introducing JSX – React (reactjs.org)


This allows for support for bridging Susha into JSX apps.
(Hopefully) for example GitHub - vercel/satori: Enlightened library to convert HTML and CSS to SVG

Which uses JSX-RL-objects if you don’t have JSX parsing.


Get the latest potentially unstable BETA release at the git
v0.0.8 - The Susha to JSX Update

3 Likes

I might make a Babel Plugin for handing this if I ever get the time and knowledge.

3 Likes


New badge for Susha !!
Along with other SVG’s pushed to /_Asri Meta

Now you can show your Asri & Susha Flair!!


Asri/_Asri Meta/ProSushaBADGE.svg at main · SpcFORK/Asri (github.com)

2 Likes

v0.0.9 - The RenderLoop Update

-=- View DOCUMENTATION -=-

New Features


  • RenderLoop and packRenderer
    This allows you to attach render loops to your elements to update per _ ms, allowing you to create dynamic render loops.
Code
import { registerComp } from '/src/_helper/registerComp.js'

/**
 * No operation function.
 */
const noop = _ => { },

/**
 * Asynchronous no operation function.
 */
  Anoop = async _ => { },

/**
 * Dispatches a custom event on the provided element.
 *
 * @param {HTMLElement} el - The element on which to dispatch the event.
 * @param {string} eventName - The name of the event.
 * @param {Object} [data={}] - Additional data to pass with the event.
 * @returns {CustomEvent} The dispatched event.
 */
  qEvent = (el, eventName, data = {}) => {
    const event = new CustomEvent(eventName, {
      detail: {
        element: el,
        data
      },
      bubbles: true,
      cancelable: true
    })

    {
      (el?.get$
        ? el.get$()
        : el
      ).dispatchEvent(event)
    }

    return event
  }

/**
 * Starts a render loop for the given entry element.
 *
 * @async
 * @function RenderLoop
 * @param {HTMLElement} entry - The entry element to render.
 * @param {Function} [fn=Anoop] - The function to execute each frame.
 * @param {number} [delay=0] - Delay before each invocation of `fn`.
 * @returns {number} The requestAnimationFrame identifier for the render loop.
 */
export async function RenderLoop(entry, fn = Anoop, delay = 0) {
  let
    rAF_ = requestAnimationFrame,
    STOP = false,

    render = async _ => {
      await sleep(delay)

      const
        res = await fn?.({
          entry,
          rAF: rAF_,
          stop: _ => STOP = true
        })

      if (STOP) return;

      const numeric_ = rAF_(render)

      qEvent(entry, 'render', {
        ...res,
        numeric_: numeric_
      })
    }

  return rAF_(render)
}

/**
 * Creates a packRenderer function for the given element.
 *
 * @function packRenderer
 * @param {HTMLElement} element - The element for which to create the renderer.
 * @returns {Function} A function that starts a render loop when invoked.
 */
export const packRenderer = element => (
  (fn = Anoop, delay = 0) => {
    return RenderLoop(element, fn, delay)
  }
)

{
  [RenderLoop, packRenderer].map(registerComp)
}

export default {
  RenderLoop,
  packRenderer
}
AI Summary

This is Susha code that imports a helper function and defines several other utility functions for managing events and rendering operations.

  • import { registerComp } from '/src/_helper/registerComp.js':
    This line imports a function named registerComp from another JavaScript file, presumably used to register components for later use.
  • const noop = _ => { }:
    noop is a name often given to a “no operation” function, which is a function that does nothing. In JavaScript, _ => {} is an arrow function that takes a single parameter (which is ignored, hence the underscore naming convention) and has an empty body. It’s essentially a placeholder function that’s used when a functional argument is needed, but you don’t actually want it to do anything.
  • const Anoop = async _ => { }:
    Similar to noop, Anoop stands for “asynchronous no operation”. It’s an asynchronous version of noop, which means it returns a Promise that resolves immediately. It can be used in contexts where an async function is required, and you want it to effectively do nothing.
  • qEvent is a function for dispatching custom events. It takes an HTMLElement el, an event name eventName, and an optional data object data (defaulting to an empty object). It creates a new CustomEvent with the given name and details, dispatches it on the provided element, and then returns the event. This allows for communication between different parts of the application by signaling that something has occurred.
  • RenderLoop is an async function that starts a render loop for a given HTML entry element. It uses requestAnimationFrame to perform an operation defined by function fn (defaulting to Anoop) in a loop, with a specified delay before each call to fn. It also dispatches a custom event with qEvent to signal each render. The loop can be stopped by setting STOP to true. RenderLoop returns the ID that requestAnimationFrame provides, which can be used for cancellation with cancelAnimationFrame.
  • packRenderer is a higher-order function that returns a new function tailored to start a render loop for a specific HTML element. When that returned function is called with fn and delay, it starts the render loop on the element it was created for.
  • The final lines with the array and map call [RenderLoop, packRenderer].map(registerComp) are used to register the RenderLoop and packRenderer functions using the previously imported registerComp function. This might be a part of a system or framework that requires explicit registration of such functions.
  • export default { RenderLoop, packRenderer }:
    Finally, this line exports RenderLoop and packRenderer as part of the module’s default export, enabling other files to import them.

Importing


image

Code for the Above image
  static async preload() {
    pageLoadedIcon.style$({
      'border-radius': '25%',
    })

    return [
      await addStringInvoke(),
      await addRenderLoop()
    ]
  }
  • You can import it using the global addRenderLoop() call.
    • This will put it into window.Components just incase you’ll need it elsewhere.

Constructing


image

  • Constructing it in an Entry Main is easy, just act like the position of the Module in the array is your import, and it works like any other framework,

    But running in a Sync, default type script tag. :slight_smile:
    (You could do this in MJS and etc!)

    constructor(entry, mods) {
        const { RenderLoop, packRenderer } = mods[1]
    
        let ePack = window.ePack$ = packRenderer(entry)
    
        ePack(async _ => {
          console.log('Entry Packed!')
        }, 100)
    
        // . . .
    }
    
fullSource
window.Main = class Main {

  /*
    This class automatically inherits:
      - The entry element,
      - The page pathname,
      - The file location.

    this.entry, this.path, this.entryPath,
  */

  static magicI = 'ı'
  static name = `Asr${Main.magicI}`
  static version = '0.0.8 - The `Susha to JSX` Update'

  static PageTitle = Main.name

  static async preload() {
    pageLoadedIcon.style$({
      'border-radius': '25%',
    })

    return [
      await addStringInvoke(),
      await addRenderLoop()
    ]
  }

  static vv = visualViewport

  static centerStyle = {
    position: 'absolute',
    top: `${this.vv.height / 2}px`,
    left: `${this.vv.width / 2}px`,
    transform: 'translate(-50%, -50%)',
  }

  // ---

  static arrStr = (...arr) => arr.join('<br />')

  title = h1(`Asr${Main.magicI}`)
    .style$({
      fontSize: '3rem',
      color: 'white',
      textAlign: 'center',
      // margin: '0',

      // Orange to white Text shadow
      textShadow: '0 0 10px #db750080, 0 0 20px #db750075, 0 0 30px #db750070',
      color: '#db7500'
    })

  small = small(`v${Main.version}`);

  artTitle = h2('Stack Altogether');
  art1Text = p()
    .html$(Main.arrStr(
      'Welcome to Asri,',

      '',

      'A starter for simple SpcFORKit websites.',
      'It is a simple, yet powerful,',

      '',

      div(
        hr(),
        h2(`v${Main.version}`),
        hr()
      ).outerHTML,

      "Recently, we've have added:",

      ul(
        li('A bridge for converting ChubML to HTML to Susha (SushaWrapper).'),
        li('A bridge for converting Susha to JSX.'),
        li('Advanced MJS Components, and `/src/_helper/`s!!')
      ).outerHTML,

      i('Be on the lookout for more ', b('frequent'), ' updates in the future.').outerHTML,

      '',
    ));

  art1 = article(
    this.artTitle,
    this.art1Text
  );

  srcButton = button('Source Code')
    .att$(
      'onclick',
      stringInvoke(_ => {
        window.open("https://github.com/SpcFORK/Asri")
      })
    )
    .att$('type', 'button')
    .html$('Source Code')

  fileButton = button('File')
    .att$(
      'onclick',
      stringInvoke(_ => {
        window.open("src/m/GrechaSusha.js", window.location)
      })
    )
    .att$('type', 'button')
    .html$('File')
    .style$({
      'background-color': '#aaa3',
    })

  ReplButton = button('Make Repl')
    .att$(
      'onclick',
      stringInvoke(_ => {
        window.open(
          'https://replit.com/new?tab=replit&language=html&template=160910a4-5017-4602-81e0-a948bc939a6a',
          '_blank'
        )
      })
    )
    .att$('type', 'button')
    .html$('Make a new Asri (Replit) Repl')
    .style$({
      'background-color': '#aaa3',
      'margin-top': '0.5rem',
    })

  buttonBar = div(

    this.srcButton,
    this.fileButton

  ).style$({
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    gap: '0.5rem',
  })

  struct1 = div(
    section(
      this.title,
      hr(),

      this.small,
      hr(),

      this.art1,
      hr(),

      this.buttonBar,
      this.ReplButton
    ).style$({
      ...Main.centerStyle,
      fontSize: '1em',
      transform: 'translate(-50%, -55%)',
    }),
  )

  struct2 = div(
    section(

      h1('What is Asri?'),
      hr(),

      h3('A simple solution.'),

      pre('Asri allows for users to make pages quickly and dynamically, \nwhile keeping the codebase small and simple.'),

      hr(),

      h3('How?'),
      pre('The libraries featured in Asri allow for the user to create \npages quickly and dynamically, while keeping the codebase small and simple.'),

      hr(),
      p(b('To do this; we leverage')),

      ul(
        li('ChubML'),
        li('Grecha Susha'),
        li('Asri Runner')
      ),

      hr(),

      h3('More'),

      pre('To learn more about Asri outside of this page, check out our'),

      ul(
        li(
          a(b('GITHUB'))
            .att$('target', '_blank')
            .att$('href', 'https://github.com/SpcFORK/Asri')
        ),

        li(
          a(b('DISCORD'))
            .att$('target', '_blank')
            .att$('href', 'https://discord.gg/' + atob('QmZ4S1Z2c2E4VQ=='))
        ),
      ),

      pre('Or, read the source code!')

    ).style$({
      ...Main.centerStyle,
      fontSize: '1em',
      top: '150%'
    })
  )

  // ---

  footer = tag(
    'footer',
    small(`Made with ❤️ by SpcFORK - ${Main.name} v${Main.version} - Copyright © ${new Date().getFullYear()}`),
  ).style$({
    ...Main.centerStyle,
    fontSize: '1em',
    transform: 'translate(-50%, -65%)',
    top: '200%',
    padding: '1rem',
  })

  // ---

  constructor(entry, mods) {
    const { RenderLoop, packRenderer } = mods[1]

    let ePack = window.ePack$ = packRenderer(entry)

    // ePack(async _ => {
    //   console.log('Entry Packed!')
    // }, 100)

    entry.append(
      router({
        '/': () => div(
          this.struct1.get$().cloneNode(true),
          this.struct2.get$().cloneNode(true),
          this.footer.get$().cloneNode(true)
        ),

        '/docs': () => div(
          h1('Docs'),
          hr(),
          pre('Coming soon, check back on this later!\n\n- SpcFORK'),
          this.footer
            .style$({
              top: '97%',
            })
            .get$()
            .cloneNode(true)
        ),
      })
    )
  }

}

Get the latest potentially unstable BETA release at the git
v0.0.9 - The RenderLoop Update

1 Like