diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index a77032c..0000000 --- a/docs/404.html +++ /dev/null @@ -1,878 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- -

404 - Not found

- -
-
- - - - -
- - - -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/assets/images/favicon.ico b/docs/assets/images/favicon.ico deleted file mode 100644 index 5ce7e0f..0000000 Binary files a/docs/assets/images/favicon.ico and /dev/null differ diff --git a/docs/assets/images/favicon.png b/docs/assets/images/favicon.png deleted file mode 100644 index 1cf13b9..0000000 Binary files a/docs/assets/images/favicon.png and /dev/null differ diff --git a/docs/assets/images/fronty.png b/docs/assets/images/fronty.png deleted file mode 100644 index 0b0314b..0000000 Binary files a/docs/assets/images/fronty.png and /dev/null differ diff --git a/docs/assets/images/logo.png b/docs/assets/images/logo.png deleted file mode 100644 index 51c861a..0000000 Binary files a/docs/assets/images/logo.png and /dev/null differ diff --git a/docs/assets/javascripts/bundle.fac441b0.min.js b/docs/assets/javascripts/bundle.fac441b0.min.js deleted file mode 100644 index 4bb4cd6..0000000 --- a/docs/assets/javascripts/bundle.fac441b0.min.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict";(()=>{var Ci=Object.create;var gr=Object.defineProperty;var Ri=Object.getOwnPropertyDescriptor;var ki=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Hi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var rn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&rn(e,r,t[r]);if(Ht)for(var r of Ht(t))nn.call(t,r)&&rn(e,r,t[r]);return e};var on=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&nn.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Pi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ki(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=Ri(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ci(Hi(e)):{},Pi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var sn=Pt((xr,an)=>{(function(e,t){typeof xr=="object"&&typeof an!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(O){return!!(O&&O!==document&&O.nodeName!=="HTML"&&O.nodeName!=="BODY"&&"classList"in O&&"contains"in O.classList)}function f(O){var Qe=O.type,De=O.tagName;return!!(De==="INPUT"&&s[Qe]&&!O.readOnly||De==="TEXTAREA"&&!O.readOnly||O.isContentEditable)}function c(O){O.classList.contains("focus-visible")||(O.classList.add("focus-visible"),O.setAttribute("data-focus-visible-added",""))}function u(O){O.hasAttribute("data-focus-visible-added")&&(O.classList.remove("focus-visible"),O.removeAttribute("data-focus-visible-added"))}function p(O){O.metaKey||O.altKey||O.ctrlKey||(a(r.activeElement)&&c(r.activeElement),n=!0)}function m(O){n=!1}function d(O){a(O.target)&&(n||f(O.target))&&c(O.target)}function h(O){a(O.target)&&(O.target.classList.contains("focus-visible")||O.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(O.target))}function v(O){document.visibilityState==="hidden"&&(o&&(n=!0),Q())}function Q(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function B(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(O){O.target.nodeName&&O.target.nodeName.toLowerCase()==="html"||(n=!1,B())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Q(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var cn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},s=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(B,N){d.append(N,B)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(O){throw new Error("URL unable to set base "+c+" due to "+O)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Q=!0,B=this;["append","delete","set"].forEach(function(O){var Qe=h[O];h[O]=function(){Qe.apply(h,arguments),v&&(Q=!1,B.search=h.toString(),Q=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,Q&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(f){Object.defineProperty(s,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){a(f)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var qr=Pt((Mt,Nr)=>{/*! - * clipboard.js v2.0.11 - * https://clipboardjs.com/ - * - * Licensed MIT © Zeno Rocha - */(function(t,r){typeof Mt=="object"&&typeof Nr=="object"?Nr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ai}});var s=i(279),a=i.n(s),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var E=p()(T);return m("cut"),E},h=d;function v(j){var T=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[T?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var Q=function(T,E){var H=v(T);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},B=function(T){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof T=="string"?H=Q(T,E):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?H=Q(T.value,E):(H=p()(T),m("copy")),H},N=B;function O(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?O=function(E){return typeof E}:O=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},O(j)}var Qe=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=T.action,H=E===void 0?"copy":E,I=T.container,q=T.target,Me=T.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&O(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function Ei(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function tn(j,T){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=c()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ai=Li},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,f){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(f))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return c(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),s=f.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var f=this;function c(){f.off(i,c),s.apply(a,arguments)}return c._=s,this.on(i,c,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=a.length;for(f;f{"use strict";/*! - * escape-html - * Copyright(c) 2012-2013 TJ Holowaychuk - * Copyright(c) 2015 Andreas Lubbe - * Copyright(c) 2015 Tiancheng "Timothy" Gu - * MIT Licensed - */var rs=/["'&<>]/;Yo.exports=ns;function ns(e){var t=""+e,r=rs.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof et?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function pn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,f){s=e[i](s),o(a,f,s.done,s.value)})}}function o(i,s,a,f){Promise.resolve(f).then(function(c){i({value:c,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: -`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` - `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{ln(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ln(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function ln(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new xn(r,n)},t}(F);var xn=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,f=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Sn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Oe=new Sn(wn);var _=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Te(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=zi();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return un(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return Ni(e);if(pt(e))return qi(e);if(Nt(e))return Ki(e);if(Kt(e))return On(e);if(Gt(e))return Qi(e);if(Jt(e))return Yi(e)}throw Qt(e)}function Ni(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function qi(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Dn(function(){return new Zt}))}}function Vn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,f=a===void 0?!0:a;return function(c){var u,p,m,d=0,h=!1,v=!1,Q=function(){p==null||p.unsubscribe(),p=void 0},B=function(){Q(),u=m=void 0,h=v=!1},N=function(){var O=u;B(),O==null||O.unsubscribe()};return y(function(O,Qe){d++,!v&&!h&&Q();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,f))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,Q(),p=$r(B,o,$e),De.error($e)},complete:function(){h=!0,Q(),p=$r(B,s),De.complete()}}),U(O).subscribe(u))})(c)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),J())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Kn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>rr(e)),V(rr(e)))}var Yn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Wr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),va?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Wr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ba.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Gn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Jn=typeof WeakMap!="undefined"?new WeakMap:new Yn,Xn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ga.getInstance(),n=new La(t,r,this);Jn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Xn.prototype[e]=function(){var t;return(t=Jn.get(this))[e].apply(t,arguments)}});var Aa=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Xn}(),Zn=Aa;var eo=new x,Ca=$(()=>k(new Zn(e=>{for(let t of e)eo.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ca.pipe(S(t=>t.observe(e)),g(t=>eo.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var to=new x,Ra=$(()=>k(new IntersectionObserver(e=>{for(let t of e)to.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function sr(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function ro(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),J())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function no(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function ka(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ha(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function oo(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:no("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!ka(n,r)}return!0}),pe());return Ha().pipe(g(t=>t?_:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function io(){return new x}function ao(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)ao(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)ao(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function so(){return location.hash.substring(1)}function Dr(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Pa(e){return L(b(window,"hashchange"),e).pipe(l(so),V(so()),A(t=>t.length>0),X(1))}function co(e){return Pa(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function Vr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function fo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function zr(e,t){return e.pipe(g(r=>r?t():_))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>_),g(r=>r.status!==200?Ot(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),X(1))}function uo(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),X(1))}function pr(e){let t=M("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function po(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function lo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(po),V(po()))}function mo(){return{width:innerWidth,height:innerHeight}}function ho(){return b(window,"resize",{passive:!0}).pipe(l(mo),V(mo()))}function bo(){return Y([lo(),ho()]).pipe(l(([e,t])=>({offset:e,size:t})),X(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(ee("size")),o=Y([n,r]).pipe(l(()=>Xe(e)));return Y([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:f,y:c}])=>({offset:{x:s.x-f,y:s.y-c+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,f,c)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:f,error:c});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Blog

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/css/attributes.html b/docs/components/css/attributes.html deleted file mode 100644 index 1e107b6..0000000 --- a/docs/components/css/attributes.html +++ /dev/null @@ -1,1032 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Attributes - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Attributes of CSS Components

-

Attributes

-

properties

-

properties is a dictionary that contains all the properties of a CSS component. It is a required attribute of a Selector element. You have to pass a dictionary to this attribute. The keys of the dictionary are the properties of the CSS component and the values of the dictionary are the values of the properties. Here is an example:

-
Example of properties attribute
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
from fronty.css import CSS, Selector, Style
-
-css = CSS(
-    Selector('body')
-    .properties({
-        "background-color": "red",
-        "color": "white",
-        "font-size": "20px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    })
-)
-
-print(css.render())
-
-

Output:

-
Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}
-
-

Fronty returns every frontend code minified for better performance.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/css/introduction.html b/docs/components/css/introduction.html deleted file mode 100644 index d158038..0000000 --- a/docs/components/css/introduction.html +++ /dev/null @@ -1,1284 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

CSS Components

-

What are CSS Components?

-

CSS components are a list of dictionary that can be used to create a CSS styling fast and easily. These components are very easy to use and can be used to create a CSS styling in a few lines of code. Here is lots of customization options are available. Let's get started.

-

Important CSS Components

-

CSS : To create a css in a html website.

-

Selector : To create a selector in a html website. It is like query selector in JavaScript.

-

Style : To create a style in a html website.

-

Using CSS Components

-

To use CSS components, you have to import the fronty.css module methods. CSS, Selector and Style are the methods of fronty.css module. Here is an example of using fronty.css module methods:

-
Example of importing fronty.css module
1
-2
-3
-4
-5
-6
-7
from fronty.css import CSS, Selector, Style
-
-css = CSS(
-    Selector('body')
-)
-
-print(css.render())
-
-

With this you can create a selector in a html website. But it is not enough to create a css file. You have to add some properties to the selector. To add properties to the selector, you have to use the properties attribute of the Selector element. Here is an example:

-
Example of properties attribute
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
from fronty.css import CSS, Selector, Style
-
-css = CSS(
-    Selector('body')
-    .properties({
-        "background-color": "red",
-        "color": "white",
-        "font-size": "20px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    })
-)
-
-print(css.render())
-
-

Output:

-
Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}
-
-

Here we have provided a dictionary in properties method of Selector class. The keys of the dictionary are the properties of the CSS component and the values of the dictionary are the values of the properties. You can add as many properties as you want. You can also add multiple selectors in a CSS file. Here is an example:

-
Example of multiple selectors
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
from fronty.css import CSS, Selector, Style
-
-css = CSS(
-    Selector('body')
-    .properties({
-        "background-color": "red",
-        "color": "white",
-        "font-size": "20px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    }),
-    Selector('h1')
-    .properties({
-        "color": "blue",
-        "font-size": "30px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    })
-)
-
-print(css.render())
-
-

Output:

-
Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}
-
-

You can also add multiple properties in a selector. Here is an example:

-
Example of multiple properties
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
from fronty.css import CSS, Selector, Style
-
-css = CSS(
-    Selector('body')
-    .properties({
-        "background-color": "red",
-        "color": "white",
-        "font-size": "20px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    })
-    .properties({
-        "color": "blue",
-        "font-size": "30px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    })
-)
-
-print(css.render())
-
-

Output:

-
Output of the above code
body{background-color:red;color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}
-
-

Here we can see, only the unique properties are added to the selector and the duplicate properties are overwritten with the new properties.

-

Using Style Component

-

You can also use the Style component to create a CSS file. Here is an example:

-
Example of Style component
1
-2
-3
-4
-5
-6
-7
-8
-9
from fronty.css import CSS, Selector
-from fronty.html import Style
-
-css = CSS(
-    Style('body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}'),
-    Style('h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}')
-)
-
-print(css.render())
-
-

Output:

-
Output of the above code
<style type="text/css" href="" rel="stylesheet">body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style><style type="text/css" href="" rel="stylesheet">h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style>
-
-

This is very unrealistic to create a style component like this. But you can use this method to add a CSS to your website. Here is an example:

-
Example of Style component
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
from fronty.css import CSS, Selector
-from fronty.html import Html, Head, Title, Meta, Style, Body, H1
-
-css = CSS(
-    Selector('body')
-    .properties({
-        "background-color": "red",
-        "color": "white",
-        "font-size": "20px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    }),
-    Selector('h1')
-    .properties({
-        "color": "blue",
-        "font-size": "30px",
-        "font-weight": "bold",
-        "padding": "10px",
-        "border-radius": "5px",
-        "border": "1px solid black"
-    }),
-)
-
-...
-# Now we will add the style component to the html component
-
-html = Html(
-    Head(
-        Title('My Website'),
-        Meta(charset="UTF-8"),
-        Meta(name="viewport", content="width=device-width, initial-scale=1.0"),
-        Style(css.render())
-    ),
-    Body(
-        H1('Hello World')
-    )
-)
-
-print(html.render())
-
-

Output:

-
Output of the above code
<!DOCTYPE html><html><head><title>My Website</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style type="text/css" href="" rel="stylesheet">body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style></head><body><h1>Hello World</h1></body></html>
-
-

This is how you can add a CSS to your website fast, easily and efficiently with Style component.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/html/attributes.html b/docs/components/html/attributes.html deleted file mode 100644 index ca99325..0000000 --- a/docs/components/html/attributes.html +++ /dev/null @@ -1,1172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Attributes - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Attributes of Component Elements

-

Attributes

-

The attributes of the component elements are the same as the attributes of the html elements. You can use the attributes of the html elements in the component elements. Check the attributes of the html elements.

-

Important attributes

-

id

-

The id attribute is used to give a unique id to a component element. You can use this id to select the component element using JavaScript. Element().id('something') or Element(id='something') can be used to set the id of a component element.

-

class

-

The class attribute is used to give multiple classes to a component element. You can use the same method again to override the previous class. Element().class_('something1 something2 somethingNth') or Element(class='something1 something2 somethingNth') can be used to set the class of a component element. You can also use class_ instead of class to set the class of a component element as class is a reserved keyword in Python and every programming language.

-

placeholder

-

The placeholder attribute is used to set the placeholder of a field. Element().placeholder('something') or Element(placeholder='something') can be used to set the placeholder of a field. It is a method in the BaseElement class. You can use this any element that accepts the placeholder attribute as it is defined in the BaseElement class.

-

type

-

The type attribute is used to set the type of a field. Element().type('something') or Element(type='something') can be used to set the type of a field. It is a method in the BaseElement class. You can use this any element that accepts the type attribute as it is defined in the BaseElement class.

-

name

-

The name attribute is used to set the name of a field. Element().name('something') or Element(name='something') can be used to set the name of a field. It is a method in the BaseElement class. You can use this any element that accepts the name attribute as it is defined in the BaseElement class.

-

style

-

The style attribute is used to give inline CSS to a component element. You can use the same method again to override the previous style. Element().style(color='red', background_color='blue') can be used to set the style of a component element. This method takes keyword arguments as the CSS properties and their values. Some CSS properties have hyphen in their name. You can use underscore instead of hyphen in the name of the CSS properties. For example, background-color can be written as background_color.

-

attr

-

The attr attribute is used to give attributes to a component element. You can add as much as you need attributes to a component element. Element().attr('key', 'value').attr('more', 'more') can be used to set the attribute of a component element. This method takes two arguments as the key and value of the attribute.

-

required

-

The required attribute is used to make a input field required. Element().required can be used to make a input field required. It is just a property of the Input component element. You can use this any element that accepts the required attribute as it is defined in the BaseElement class.

-

disabled

-

The disabled attribute is used to make a input field disabled. Element().disabled can be used to make a input field disabled. It is just a property of the Input component element. You can use this any element that accepts the disabled attribute as it is defined in the BaseElement class.

-

readonly

-

The readonly attribute is used to make a input field readonly. Element().readonly can be used to make a input field readonly. It is just a property of the Input component element. You can use this any element that accepts the readonly attribute as it is defined in the BaseElement class.

-

value

-

The value attribute is used to set the value of a field. Element().value('something') or Element(value='something') can be used to set the value of a field. It is a method in the BaseElement class. You can use this any element that accepts the value attribute as it is defined in the BaseElement class.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/html/introduction.html b/docs/components/html/introduction.html deleted file mode 100644 index c15d65f..0000000 --- a/docs/components/html/introduction.html +++ /dev/null @@ -1,1062 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

HTML Components

-

What are HTML Components?

-

HTML components are some simple set of classes that can be used to create a HTML website fast and easily. These components are very easy to use and can be used to create a HTML website in a few lines of code. Try to create a HTML website using these components and you will see how easy it is to create a HTML website using these components. So, let's get started.

-

Built-in HTML Components

-

Html : To create the main HTML page layout.

-

Head : To create the head section of a html website.

-

Title: To describe the title of a website in the head section.

-

Meta : To describe all types of meta tags for SEO.

-

Body : To create the body structure of a html website.

-

Script: To load Javascript codes in fronty based website.

-

Style: To write custom CSS fronty.

-

Link : To load CSS codes in fronty based website.

-

Anchor : To create a anchor links in a html website.

-

Image : To load images in a html website.

-

Button : To create a button in a html website.

-

Input : To create a input field in a html website.

-

Text : To create a text in a html website.

-

Break : To create a break line in a html website.

-

Form : To create a form in a html website.

-

Div : To create a div in a html website.

-

Span : To create a span in a html website.

-

H1 : To create a h1 in a html website.

-

H2 : To create a h2 in a html website.

-

H3 : To create a h3 in a html website.

-

H4 : To create a h4 in a html website.

-

H5 : To create a h5 in a html website.

-

H6 : To create a h6 in a html website.

-

P : To create a p in a html website.

-

Ul : To create a ul in a html website.

-

Ol : To create a ol in a html website.

-

Li : To create a li in a html website.

-

Table : To create a table in a html website.

-

Tr : To create a tr in a html website.

-

Td : To create a td in a html website.

-

Th : To create a th in a html website.

-

Caption : To create a caption in a html website.

-

Thead : To create a thead in a html website.

-

Tbody : To create a tbody in a html website.

-

Tfoot : To create a tfoot in a html website.

-

Iframe : To create a iframe in a html website.

-

Audio : To create a audio in a html website.

-

Video : To create a video in a html website.

-

Source : To create a source in a html website.

-

Select : To create a select in a html website.

-

Option : To create a option in a html website.

-

Nav : To create a nav in a html website.

-

Header : To create a header in a html website.

-

Footer : To create a footer in a html website.

-

Section : To create a section in a html website.

-

Article : To create a article in a html website.

-

Aside : To create a aside in a html website.

-

Main : To create a main in a html website.

-

Figure : To create a figure in a html website.

-

Figcaption : To create a figcaption in a html website.

-

Dl : To create a dl in a html website.

-

Dt : To create a dt in a html website.

-

Dd : To create a dd in a html website.

-

Time : To create a time in a html website.

-

Mark : To create a mark in a html website.

-

Small : To create a small in a html website.

-

Strong : To create a strong in a html website.

-

Em : To create a em in a html website.

-

Code : To create a code in a html website.

-

Pre : To create a pre in a html website.

-

Blockquote : To create a blockquote in a html website.

-

Empty : To wrap multiple elements to return a single element.

-

Comment : To create a comment in a html website.

-

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/introduction.html b/docs/components/introduction.html deleted file mode 100644 index 678a4b9..0000000 --- a/docs/components/introduction.html +++ /dev/null @@ -1,1011 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Components

-

What are Components?

-

Components are the building blocks of your application. They are reusable UI elements that can be composed together to build a UI. Components are also the unit of encapsulation for the UI, CSS, and behavior. Components for manipulating HTML, CSS, and JavaScript from Python code are provided by the fronty package. Components are created by subclassing the fronty.html.BaseElement class. We will learn more about components in the customizing components section.

-

Built-in Components

-

Fronty provides a set of built-in components that can be used to create a UI. These components are:

-

For JavaScript

-

Till now, there is no built-in component for JavaScript. But you can use the Script component to load JavaScript codes in your website from js file.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/components/js/introduction.html b/docs/components/js/introduction.html deleted file mode 100644 index dd0376f..0000000 --- a/docs/components/js/introduction.html +++ /dev/null @@ -1,968 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Javascript Components

-

What are Javascript Components?

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/contribution.html b/docs/contribution.html deleted file mode 100644 index c6fb58c..0000000 --- a/docs/contribution.html +++ /dev/null @@ -1,917 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Contribution - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Contribution

-

Pull requests are welcome. For any changes, please open an issue first to discuss what you would like to change.

-

Thanks for using Fronty!

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/customization/customized-html.html b/docs/customization/customized-html.html deleted file mode 100644 index fe3d950..0000000 --- a/docs/customization/customized-html.html +++ /dev/null @@ -1,1013 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - HTML Customization - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Customizing Components

-

You can customize the built-in components or create your own components by subclassing the fronty.html.BaseElement class. Let's see how to create a custom component.

-
custom_components.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
from fronty.html import (
-    BaseElement,
-    Text
-)
-
-
-class CustomComponent(BaseElement):
-    def __init__(self, *children, **attributes):
-        super().__init__('custom-component', *children, **attributes)
-
-        # Optional attributes if you want to add any custom attributes
-        self._attributes['custom-attribute'] = 'custom-value'
-
-        # Optional children if you want to add any custom children
-        self._children = [
-            Text('This is a custom component.'),
-        ]
-
-

Now, you can use this component in your application.

-
main.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
from flask import Flask # or any other framework
-from fronty.html import (
-    Html,
-    Head,
-    Title,
-    Body,
-)
-from custom_components import CustomComponent # import the custom component
-
-app = Flask(__name__)
-
-def layout():
-    return Html(
-        Head(
-            Title('Custom Component')
-        ),
-        Body(
-            CustomComponent()
-        )
-    )
-
-
-@app.route('/')
-def home():
-    return layout().render()
-
-
-if __name__ == '__main__':
-    app.run(debug=True)
-
- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/examples.html b/docs/examples.html deleted file mode 100644 index 88282c9..0000000 --- a/docs/examples.html +++ /dev/null @@ -1,995 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Examples - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Example projects

-

Project URL: Starter project

-

Starter Project

-

Project URL: Bootstrap Integration

-

Bootstrap Integration

-

Project URL: Custom CSS Project

-

Custom CSS Project

-

Custom CSS Project

-

How to run the example projects?

-

You can easily run the example projects by cloning the Fronty repository and running the following commands in your terminal.

-
    -
  1. Clone the Fronty repository.
  2. -
  3. -

    Go to the examples/starter project directory.
    -

    cd fronty/examples/starter\ project
    -

    -
  4. -
  5. -

    Run the following command in your terminal. -

    python app.py
    -

    -
  6. -
  7. -

    Open your browser and go to http://localhost:5000 -Starter Project

    -
  8. -
  9. -

    You can also run the other example projects by going to their directories and running the same command.

    -
  10. -
  11. -

    Note: You have to install a backend server to run the project. Fronty does not provide a backend server. You can use any backend server you want. For example, you can use Flask. You can also use Fronty with Django. But you have to install Django first. For simplicity, we have used Flask in the example projects. We are woring on a backend server for Fronty. It will be available soon.

    -
  12. -
- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 2c1b4d5..0000000 --- a/docs/index.html +++ /dev/null @@ -1,1003 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Fronty

-

logo

-

-A frontend web framework for the web -

-

Created by Md. Almas Ali

-

pypi -Hits -Total downloads -This month downloads -license -stars

-
-

Documentation: https://almas-ali.github.io/fronty

-

Source Code: https://github.com/Almas-Ali/fronty

-
-

Fronty is a lightweight, fast, and easy-to-use Python-based frontend web framework that simplifies web development by allowing developers to create web pages using only Python. Its simple syntax and intuitive design make it an excellent option for beginners or developers who prefer working with Python.

-

The key features are:

-
    -
  • Python-based frontend web framework
  • -
  • No need to use HTML, CSS, or JavaScript (though you can if you want)
  • -
  • Simple and lightweight
  • -
  • Fast rendering times
  • -
  • Easy to use and customize
  • -
  • Can integrate with other Python libraries and frameworks, such as Flask, Django, FastAPI, etc.
  • -
  • Growing community with extensive documentation and resources.
  • -
-

Sponsors

-

No sponsors yet. Be the first one to sponsor this project. Become a sponsor

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/installation.html b/docs/installation.html deleted file mode 100644 index 3a9bd5e..0000000 --- a/docs/installation.html +++ /dev/null @@ -1,926 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Installation - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Installation

-

You can easily install Fronty using pip. Just run the following command in your terminal.

-
pip install fronty
-
-

You can also install a backend framework to use with Fronty. For example, if you want to use Fronty with Flask, you can checkout flask documentation https://flask.palletsprojects.com/en/2.1.x/installation/

-

If you want to use Fronty with Django, you can checkout django documentation https://docs.djangoproject.com/en/4.2/topics/install/

-

If you want to use Fronty with FastAPI, you can checkout fastapi documentation https://fastapi.tiangolo.com/tutorial/first-steps/

-
-

Start learning Fronty by reading the documentation.

-

Want to contribute? Check out the Github project.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/projects/bootstrap-integration.html b/docs/projects/bootstrap-integration.html deleted file mode 100644 index c94bd1d..0000000 --- a/docs/projects/bootstrap-integration.html +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bootstrap Integration - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Bootstrap Integration

-

Now, let's integrate Bootstrap into our project. We will use the Bootstrap CDN to load the Bootstrap CSS and JavaScript files.

-

First, we will create a new folder named components inside the project folder. Then, we will create a new component named layout.py inside the components folder.

-
project/components/layout.py
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
from fronty.html import *
-
-
-def navbar(request, **data) -> Element:
-    '''This is the navbar component'''
-
-    # The navbar layout
-    _layout = Nav(
-        Div(
-            Anchor(
-                'Fronty',
-                href='/',
-            ).class_('navbar-brand'),
-            Button(
-                Element('span').class_('navbar-toggler-icon'),
-
-            ).class_('navbar-toggler').attr('type', 'button').attr('data-bs-toggle', 'collapse').attr('data-bs-target', '#navbarScroll').attr('aria-controls', 'navbarScroll').attr('aria-expanded', 'false').attr('aria-label', 'Toggle navigation'),
-            Ul(
-                Li(
-                    Anchor(
-                        'Home',
-                        href='/',
-                    ).class_('nav-link active').attr('aria-current', 'page'),
-                ).class_('nav-item'),
-                Li(
-                    Anchor(
-                        'About',
-                        href='/about',
-                    ).class_('nav-link'),
-                ).class_('nav-item'),
-                Li(
-                    Anchor(
-                        'More',
-                        href='#',
-                    ).class_('nav-link dropdown-toggle').attr('role', 'button').attr('data-bs-toggle', 'dropdown').attr('aria-expanded', 'false'),
-                    Ul(
-                        Li(
-                            Anchor(
-                                'Action',
-                                href='#',
-                            ).class_('dropdown-item'),
-                        ),
-                        Li(
-                            Anchor(
-                                'Another action',
-                                href='#',
-                            ).class_('dropdown-item'),
-                        ),
-                        Li(
-                            Element('hr').class_('dropdown-divider'),
-                        ),
-                        Li(
-                            Anchor(
-                                'Something else here',
-                                href='#',
-                            ).class_('dropdown-item'),
-                        ),
-                    ).class_('dropdown-menu'),
-                ).class_('nav-item dropdown'),
-            ).class_('navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll').attr('style', '--bs-scroll-height: 100px;'),
-            Form(
-                Input(
-                    placeholder='Search',
-                    aria_label='Search',
-                ).class_('form-control me-2').attr('type', 'search'),
-                Button(
-                    'Search',
-                ).class_('btn btn-outline-success').attr('type', 'submit'),
-            ).class_('d-flex').attr('role', 'search'),
-
-        ).class_('container-fluid'),
-    ).class_('navbar navbar-expand-lg bg-body-tertiary')
-
-    return _layout
-
-
-def layout(request, **data) -> Html:
-    '''This is the layout component'''
-
-    # The main layout
-    return Html(
-        Head(
-            Title('Fronty'),  # Page title
-            Meta(charset='utf-8'),  # Character encoding
-            # Responsive design
-            Meta(name='viewport', content='width=device-width, initial-scale=1'),
-
-            # Bootstrap CSS
-            Link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css',
-                 integrity='sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD', crossorigin='anonymous'),
-        ),
-
-        Body(
-
-            # Navbar
-            navbar(request),
-
-            # Main area of the page
-            # The main area of the page is passed as a parameter to the layout component.
-            # Get subcomponent from data or use default value
-            data.get('content', 'Empty content'),
-
-            # Bootstrap JS
-            Script(src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js", integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN', crossorigin='anonymous'),
-        ),
-    )
-
-

Now, we will create a index.py file inside the components folder. This file will contain the home page component.

-
project/components/index.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
from fronty.html import (
-    Element,
-    Div,
-    H1,
-    Text,
-    Break
-)
-
-# components
-from components.layout import layout
-
-
-def home(request, **data) -> Element:
-    '''This is the home page component'''
-
-    _layout = layout(
-        request=request,
-        content=Div(
-            H1('Home'),
-
-            Text(
-                f"""
-                    Path: {request.path}
-                    {Break()}
-                    Method: {request.method}
-
-                """
-            ),
-
-        ).class_('container text-center')
-    )
-
-    return _layout
-
-
-# We have added the about inside the index.py file for simplicity.
-# You can create a new file for the about page component.
-def about(request, **data) -> Element:
-    '''This is the about page component'''
-
-    _layout = layout(
-        request=request,
-        content=Div(
-            H1('About'),
-        ).class_('container text-center')
-    )
-
-    return _layout
-
-

Now, we will update the app.py file to use the new components.

-
project/app.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
from flask import Flask, request
-from fronty.html import *
-
-# components
-from components.index import home, about
-
-app = Flask(__name__)
-
-
-@app.route('/')
-def index():
-    '''This is the home page view function'''
-
-    return home(
-        request=request,
-        title='A simple framework to build a website only with Python.',
-    ).render()
-
-
-@app.route('/about')
-def about_view():
-    '''This is the about page view function'''
-
-    return about(
-        request=request,
-        title='A simple framework to build a website only with Python.',
-    ).render()
-
-
-if __name__ == '__main__':
-    app.run(debug=True)
-
-

Now, we will run the project and open the home page in the browser.

-
python project/app.py
-
-

Visit http://127.0.0.1:5000 in your browser.

-

Project URL: Bootstrap Integration

-

Bootstrap Integration

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/projects/custom-css-project.html b/docs/projects/custom-css-project.html deleted file mode 100644 index 00e4499..0000000 --- a/docs/projects/custom-css-project.html +++ /dev/null @@ -1,1214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Custom CSS Project - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Custom CSS Project

-

Initially, we have created a basic HTML only project. Then we have integrated Bootstrap into our project. Now, we will create a custom CSS project. We will use only Python to create this project.

-

Let's create a new project directory named custom_css_project. Then create a new file named app.py inside the custom_css_project directory.

-

Now, we will create everything in side the app.py file.

-
custom_css_project/app.py
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
from flask import Flask
-from fronty.html import *
-from fronty.css import *
-from datetime import date
-
-# CSS components
-
-def style_css():
-    '''This is the style component'''
-
-    # The CSS() is used to create a CSS object.
-    return CSS(
-
-        # The Selector() is used to create a CSS selector.
-        # Here we have used the universal selector to select all the elements.
-        # *{} means select all the elements.
-        # We have css properties inside the properties() method.
-        # Passed the css properties as keyword arguments.
-        # The properties() method returns a CSSProperties object.
-        Selector('*').properties({
-            'margin': '0',
-            'padding': '0',
-            'font-family': 'Roboto, sans-serif, Arial',
-        }),
-
-        # Here we have selected the body tag.
-        # We have used the Selector('body') to select the body tag.
-        # Selector('body').properties({}) is used to add css properties to the body tag.
-        Selector('body').properties({
-            'background-color': '#d6d6e7',
-        }),
-        Selector('nav').properties({
-            'background-color': '#484c7a',
-            'color': '#fff',
-            'padding': '20px',
-            'position': 'absolute',
-            'width': '80%',
-            'margin': '0 10%',
-            'top': '10px',
-            'border-radius': '12px'
-        }),
-        Selector('nav ul').properties({
-            'list-style': 'none',
-            'display': 'flex',
-            'flex-direction': 'row',
-            'justify-content': 'center',
-        }),
-        Selector('nav ul li').properties({
-            'margin': '0 10px'
-        }),
-        Selector('a').properties({
-            'text-decoration': 'none',
-            'color': '#fff',
-            'padding': '12px',
-            'border-radius': '12px',
-            'transition': 'all 0.3s ease-in-out',
-            'font-size': '18px',
-        }),
-        Selector('nav a:hover').properties({
-            'background-color': '#ddd',
-            'color': 'black',
-        }),
-        Selector('nav a:active').properties({
-            'background-color': '#4CAF50',
-            'color': 'white',
-        }),
-        Selector('.container').properties({
-            'margin': '90px 10%',
-            'width': '80%',
-            'text-align': 'center',
-            'padding': '20px',
-            'background-color': '#fff',
-            'border-radius': '12px',
-        }),
-        Selector('footer').properties({
-            'position': 'absolute',
-            'bottom': '10px',
-            'width': '80%',
-            'margin': '0 10%',
-            'border-radius': '12px',
-            'text-align': 'center',
-            'padding': '20px',
-            'background-color': '#484c7a',
-            'color': '#fff',
-            'font-size': '12px',
-        }),
-    )
-
-
-# Fronty components
-
-def layout(request, **data):
-    '''This is the layout component'''
-
-    # The Html() is used to create a HTML object.
-    return Html(
-        Head(
-            Title('Custom CSS Project'),
-            Meta(charset='UTF-8'),
-            Meta(content="IE=edge").attr('http-equiv', 'X-UA-Compatible'),
-            Meta(name='viewport', content='width=device-width, initial-scale=1.0'),
-            Style(
-                style_css().render(),
-            ),
-        ),
-        Body(
-            Nav(
-                Ul(
-                    Li(
-                        Anchor('Home', href='/'),
-                    ),
-                    Li(
-                        Anchor('About', href='/about'),
-                    )
-                )
-            ),
-            Div(
-                H1(
-                    'Custom CSS Project',
-                ),
-                Text(
-                    'This is a custom CSS project using Fronty.',
-                ),
-            ).class_('container'),
-            Footer(
-                f{date.today().year} Fronty',
-            ),
-        )
-    )
-
-
-app = Flask(__name__)
-
-
-@app.route('/')
-def home():
-    '''This is the home page view function'''
-
-    # The render() method is used to convert the python objects to HTML string.
-    return layout(
-        request=None,
-    ).render()
-
-
-if __name__ == '__main__':
-    app.run(debug=True)
-
- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/projects/starter-project.html b/docs/projects/starter-project.html deleted file mode 100644 index 193a52a..0000000 --- a/docs/projects/starter-project.html +++ /dev/null @@ -1,1042 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Starter Project - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Starter Project

-

For simplicity, we have created a starter project that you can use to get started with your own project. It is a simple project that contains a single page with a single component. It is a good starting point for your own project.

-
starter_project/app.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
from flask import Flask, request
-from fronty.html import *
-
-app = Flask(__name__)
-
-
-def home(request) -> Html:
-    '''This is the home page view function'''
-
-    # The main HTML element.
-    return Html(
-
-        # The head tag contains the title and meta tags.
-        Head(
-
-            # The title tag contains the title of the page.
-            Title('Home'),
-
-            # The meta tags contain the meta information of the page.
-            Meta(charset='utf-8'),
-            Meta(name='viewport', content='width=device-width, initial-scale=1'),
-        ),
-
-        # The body tag contains all the content of the page.
-        Body(
-
-            # The center tag contains the main content of the page.
-            # It is like using a HTML element when you don't know whats the name of a tag in fronty.
-            # You can use the Element('tag') for this purpose.
-            Element(
-                'center',
-
-                # The h1 tag contains the title of the page.
-                H1(
-                    'Welcome to Fronty!'
-                ),
-
-                # The Text() is used to add text to the page like paragraphs.
-                Text(
-                    'Fronty is a frontend web framework.'
-                ),
-            )
-        )
-    )
-
-
-@app.route('/')
-def index() -> str:
-    '''This is the home page view function'''
-
-    # The render() method is used to convert the python objects to HTML string.
-    # The render() method returns a string. So, we can return it directly.
-    return home(
-        request=request,
-    ).render()
-
-
-if __name__ == '__main__':
-    # Run the app in debug mode.
-    # Learn more about Flask at https://flask.palletsprojects.com/en/2.1.x/
-    app.run(debug=True)
-
- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/quick-start.html b/docs/quick-start.html deleted file mode 100644 index 8ba77a0..0000000 --- a/docs/quick-start.html +++ /dev/null @@ -1,1070 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Quick Start - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Quick Start

-

As fronty is a very simple framework, it is very easy to use. You can easily create a website using. It -is mainly focused on the frontend part. So, we haven't add any backend features. But, you can easily add -backend features using any backend framework like Flask, Django, Fastapi etc.

-

But, we are working on a backend framework for fronty named Backkr. And we are also -working on a database framework named Flexdb. So, you can easily create a full stack -website with database using Fronty in only Python technology without knowing any kind -of web technologies like HTML, CSS, and JavaScript.

-

Here we will use flask as a backend framework for making this documentation short. But, you can use any -backend framework you want. We will update this documentation when we release Backkr and Flexdb. So, you can easily create a full stack website using only Python.

-

Starter template

-
app.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
from flask import Flask, request
-from fronty.html import *
-
-app = Flask(__name__)
-
-
-def home(request) -> Html:
-    '''This is the home page view function'''
-    return Html(
-        Head(
-            Title('Home'),
-            Meta(charset='utf-8'),
-            Meta(name='viewport', content='width=device-width, initial-scale=1'),
-        ),
-        Body(
-            Element(
-                'center',
-                Element(
-                    'h1',
-                    'Welcome to Fronty!'
-                ),
-                Element(
-                    'p',
-                    'Fronty is a frontend web framework.'
-                ),
-            )
-        )
-    )
-
-
-@app.route('/')
-def index() -> str:
-    '''This is the home page view function'''
-    return home(
-        request=request,
-    ).render()
-
-
-if __name__ == '__main__':
-    app.run(debug=True)
-
-

This is a starter template for fronty. You can use this template to create a basic website using -fronty. -
-First, we import the Flask and request from flask. Then, we import Html, Head, Title, Meta, Body, -Element from fronty.html package. -
-Then, we create a flask app. Then, we create a home view function. This view function will return -a Html object. This Html object will contain the HTML code for the home page. -
-Then, we create a index view function. This view function will call the home view function and -render the HTML code. -
-Then, we run the flask app.

-

Fronty has a very simple syntax. You can easily create a website using it. It has -some built-in element like Button, Link, Anchor etc. You can use these elements to -create a website. You can also create your own element using the BaseElement class. -We will see how to create a element in the customization section.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/search/search_index.json b/docs/search/search_index.json deleted file mode 100644 index 49aba35..0000000 --- a/docs/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"index.html","title":"Fronty","text":"

A frontend web framework for the web

Created by Md. Almas Ali

Documentation: https://almas-ali.github.io/fronty

Source Code: https://github.com/Almas-Ali/fronty

Fronty is a lightweight, fast, and easy-to-use Python-based frontend web framework that simplifies web development by allowing developers to create web pages using only Python. Its simple syntax and intuitive design make it an excellent option for beginners or developers who prefer working with Python.

"},{"location":"index.html#the-key-features-are","title":"The key features are:","text":"
  • Python-based frontend web framework
  • No need to use HTML, CSS, or JavaScript (though you can if you want)
  • Simple and lightweight
  • Fast rendering times
  • Easy to use and customize
  • Can integrate with other Python libraries and frameworks, such as Flask, Django, FastAPI, etc.
  • Growing community with extensive documentation and resources.
"},{"location":"index.html#sponsors","title":"Sponsors","text":"

No sponsors yet. Be the first one to sponsor this project. Become a sponsor

"},{"location":"contribution.html","title":"Contribution","text":"

Pull requests are welcome. For any changes, please open an issue first to discuss what you would like to change.

Thanks for using Fronty!

"},{"location":"examples.html","title":"Example projects","text":"

Project URL: Starter project

Project URL: Bootstrap Integration

Project URL: Custom CSS Project

"},{"location":"examples.html#how-to-run-the-example-projects","title":"How to run the example projects?","text":"

You can easily run the example projects by cloning the Fronty repository and running the following commands in your terminal.

  1. Clone the Fronty repository.
  2. Go to the examples/starter project directory.

    cd fronty/examples/starter\\ project\n

  3. Run the following command in your terminal.

    python app.py\n

  4. Open your browser and go to http://localhost:5000

  5. You can also run the other example projects by going to their directories and running the same command.

  6. Note: You have to install a backend server to run the project. Fronty does not provide a backend server. You can use any backend server you want. For example, you can use Flask. You can also use Fronty with Django. But you have to install Django first. For simplicity, we have used Flask in the example projects. We are woring on a backend server for Fronty. It will be available soon.

"},{"location":"installation.html","title":"Installation","text":"

You can easily install Fronty using pip. Just run the following command in your terminal.

pip install fronty\n

You can also install a backend framework to use with Fronty. For example, if you want to use Fronty with Flask, you can checkout flask documentation https://flask.palletsprojects.com/en/2.1.x/installation/

If you want to use Fronty with Django, you can checkout django documentation https://docs.djangoproject.com/en/4.2/topics/install/

If you want to use Fronty with FastAPI, you can checkout fastapi documentation https://fastapi.tiangolo.com/tutorial/first-steps/

Start learning Fronty by reading the documentation.

Want to contribute? Check out the Github project.

"},{"location":"quick-start.html","title":"Quick Start","text":"

As fronty is a very simple framework, it is very easy to use. You can easily create a website using. It is mainly focused on the frontend part. So, we haven't add any backend features. But, you can easily add backend features using any backend framework like Flask, Django, Fastapi etc.

But, we are working on a backend framework for fronty named Backkr. And we are also working on a database framework named Flexdb. So, you can easily create a full stack website with database using Fronty in only Python technology without knowing any kind of web technologies like HTML, CSS, and JavaScript.

Here we will use flask as a backend framework for making this documentation short. But, you can use any backend framework you want. We will update this documentation when we release Backkr and Flexdb. So, you can easily create a full stack website using only Python.

"},{"location":"quick-start.html#starter-template","title":"Starter template","text":"app.py
from flask import Flask, request\nfrom fronty.html import *\napp = Flask(__name__)\ndef home(request) -> Html:\n'''This is the home page view function'''\nreturn Html(\nHead(\nTitle('Home'),\nMeta(charset='utf-8'),\nMeta(name='viewport', content='width=device-width, initial-scale=1'),\n),\nBody(\nElement(\n'center',\nElement(\n'h1',\n'Welcome to Fronty!'\n),\nElement(\n'p',\n'Fronty is a frontend web framework.'\n),\n)\n)\n)\n@app.route('/')\ndef index() -> str:\n'''This is the home page view function'''\nreturn home(\nrequest=request,\n).render()\nif __name__ == '__main__':\napp.run(debug=True)\n

This is a starter template for fronty. You can use this template to create a basic website using fronty. First, we import the Flask and request from flask. Then, we import Html, Head, Title, Meta, Body, Element from fronty.html package. Then, we create a flask app. Then, we create a home view function. This view function will return a Html object. This Html object will contain the HTML code for the home page. Then, we create a index view function. This view function will call the home view function and render the HTML code. Then, we run the flask app.

Fronty has a very simple syntax. You can easily create a website using it. It has some built-in element like Button, Link, Anchor etc. You can use these elements to create a website. You can also create your own element using the BaseElement class. We will see how to create a element in the customization section.

"},{"location":"blog/index.html","title":"Blog","text":""},{"location":"components/introduction.html","title":"Components","text":""},{"location":"components/introduction.html#what-are-components","title":"What are Components?","text":"

Components are the building blocks of your application. They are reusable UI elements that can be composed together to build a UI. Components are also the unit of encapsulation for the UI, CSS, and behavior. Components for manipulating HTML, CSS, and JavaScript from Python code are provided by the fronty package. Components are created by subclassing the fronty.html.BaseElement class. We will learn more about components in the customizing components section.

"},{"location":"components/introduction.html#built-in-components","title":"Built-in Components","text":"

Fronty provides a set of built-in components that can be used to create a UI. These components are:

"},{"location":"components/introduction.html#for-javascript","title":"For JavaScript","text":"

Till now, there is no built-in component for JavaScript. But you can use the Script component to load JavaScript codes in your website from js file.

"},{"location":"components/css/attributes.html","title":"Attributes of CSS Components","text":""},{"location":"components/css/attributes.html#attributes","title":"Attributes","text":""},{"location":"components/css/attributes.html#properties","title":"properties","text":"

properties is a dictionary that contains all the properties of a CSS component. It is a required attribute of a Selector element. You have to pass a dictionary to this attribute. The keys of the dictionary are the properties of the CSS component and the values of the dictionary are the values of the properties. Here is an example:

Example of properties attribute
from fronty.css import CSS, Selector, Style\ncss = CSS(\nSelector('body')\n.properties({\n\"background-color\": \"red\",\n\"color\": \"white\",\n\"font-size\": \"20px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n})\n)\nprint(css.render())\n

Output:

Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}\n

Fronty returns every frontend code minified for better performance.

"},{"location":"components/css/introduction.html","title":"CSS Components","text":""},{"location":"components/css/introduction.html#what-are-css-components","title":"What are CSS Components?","text":"

CSS components are a list of dictionary that can be used to create a CSS styling fast and easily. These components are very easy to use and can be used to create a CSS styling in a few lines of code. Here is lots of customization options are available. Let's get started.

"},{"location":"components/css/introduction.html#important-css-components","title":"Important CSS Components","text":"

CSS : To create a css in a html website.

Selector : To create a selector in a html website. It is like query selector in JavaScript.

Style : To create a style in a html website.

"},{"location":"components/css/introduction.html#using-css-components","title":"Using CSS Components","text":"

To use CSS components, you have to import the fronty.css module methods. CSS, Selector and Style are the methods of fronty.css module. Here is an example of using fronty.css module methods:

Example of importing fronty.css module
from fronty.css import CSS, Selector, Style\ncss = CSS(\nSelector('body')\n)\nprint(css.render())\n

With this you can create a selector in a html website. But it is not enough to create a css file. You have to add some properties to the selector. To add properties to the selector, you have to use the properties attribute of the Selector element. Here is an example:

Example of properties attribute
from fronty.css import CSS, Selector, Style\ncss = CSS(\nSelector('body')\n.properties({\n\"background-color\": \"red\",\n\"color\": \"white\",\n\"font-size\": \"20px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n})\n)\nprint(css.render())\n

Output:

Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}\n

Here we have provided a dictionary in properties method of Selector class. The keys of the dictionary are the properties of the CSS component and the values of the dictionary are the values of the properties. You can add as many properties as you want. You can also add multiple selectors in a CSS file. Here is an example:

Example of multiple selectors
from fronty.css import CSS, Selector, Style\ncss = CSS(\nSelector('body')\n.properties({\n\"background-color\": \"red\",\n\"color\": \"white\",\n\"font-size\": \"20px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n}),\nSelector('h1')\n.properties({\n\"color\": \"blue\",\n\"font-size\": \"30px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n})\n)\nprint(css.render())\n

Output:

Output of the above code
body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}\n

You can also add multiple properties in a selector. Here is an example:

Example of multiple properties
from fronty.css import CSS, Selector, Style\ncss = CSS(\nSelector('body')\n.properties({\n\"background-color\": \"red\",\n\"color\": \"white\",\n\"font-size\": \"20px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n})\n.properties({\n\"color\": \"blue\",\n\"font-size\": \"30px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n})\n)\nprint(css.render())\n

Output:

Output of the above code
body{background-color:red;color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}\n

Here we can see, only the unique properties are added to the selector and the duplicate properties are overwritten with the new properties.

"},{"location":"components/css/introduction.html#using-style-component","title":"Using Style Component","text":"

You can also use the Style component to create a CSS file. Here is an example:

Example of Style component
from fronty.css import CSS, Selector\nfrom fronty.html import Style\ncss = CSS(\nStyle('body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}'),\nStyle('h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}')\n)\nprint(css.render())\n

Output:

Output of the above code
<style type=\"text/css\" href=\"\" rel=\"stylesheet\">body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style><style type=\"text/css\" href=\"\" rel=\"stylesheet\">h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style>\n

This is very unrealistic to create a style component like this. But you can use this method to add a CSS to your website. Here is an example:

Example of Style component
from fronty.css import CSS, Selector\nfrom fronty.html import Html, Head, Title, Meta, Style, Body, H1\ncss = CSS(\nSelector('body')\n.properties({\n\"background-color\": \"red\",\n\"color\": \"white\",\n\"font-size\": \"20px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n}),\nSelector('h1')\n.properties({\n\"color\": \"blue\",\n\"font-size\": \"30px\",\n\"font-weight\": \"bold\",\n\"padding\": \"10px\",\n\"border-radius\": \"5px\",\n\"border\": \"1px solid black\"\n}),\n)\n...\n# Now we will add the style component to the html component\nhtml = Html(\nHead(\nTitle('My Website'),\nMeta(charset=\"UTF-8\"),\nMeta(name=\"viewport\", content=\"width=device-width, initial-scale=1.0\"),\nStyle(css.render())\n),\nBody(\nH1('Hello World')\n)\n)\nprint(html.render())\n

Output:

Output of the above code
<!DOCTYPE html><html><head><title>My Website</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style type=\"text/css\" href=\"\" rel=\"stylesheet\">body{background-color:red;color:white;font-size:20px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}h1{color:blue;font-size:30px;font-weight:bold;padding:10px;border-radius:5px;border:1px solid black}</style></head><body><h1>Hello World</h1></body></html>\n

This is how you can add a CSS to your website fast, easily and efficiently with Style component.

"},{"location":"components/html/attributes.html","title":"Attributes of Component Elements","text":""},{"location":"components/html/attributes.html#attributes","title":"Attributes","text":"

The attributes of the component elements are the same as the attributes of the html elements. You can use the attributes of the html elements in the component elements. Check the attributes of the html elements.

"},{"location":"components/html/attributes.html#important-attributes","title":"Important attributes","text":""},{"location":"components/html/attributes.html#id","title":"id","text":"

The id attribute is used to give a unique id to a component element. You can use this id to select the component element using JavaScript. Element().id('something') or Element(id='something') can be used to set the id of a component element.

"},{"location":"components/html/attributes.html#class","title":"class","text":"

The class attribute is used to give multiple classes to a component element. You can use the same method again to override the previous class. Element().class_('something1 something2 somethingNth') or Element(class='something1 something2 somethingNth') can be used to set the class of a component element. You can also use class_ instead of class to set the class of a component element as class is a reserved keyword in Python and every programming language.

"},{"location":"components/html/attributes.html#placeholder","title":"placeholder","text":"

The placeholder attribute is used to set the placeholder of a field. Element().placeholder('something') or Element(placeholder='something') can be used to set the placeholder of a field. It is a method in the BaseElement class. You can use this any element that accepts the placeholder attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#type","title":"type","text":"

The type attribute is used to set the type of a field. Element().type('something') or Element(type='something') can be used to set the type of a field. It is a method in the BaseElement class. You can use this any element that accepts the type attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#name","title":"name","text":"

The name attribute is used to set the name of a field. Element().name('something') or Element(name='something') can be used to set the name of a field. It is a method in the BaseElement class. You can use this any element that accepts the name attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#style","title":"style","text":"

The style attribute is used to give inline CSS to a component element. You can use the same method again to override the previous style. Element().style(color='red', background_color='blue') can be used to set the style of a component element. This method takes keyword arguments as the CSS properties and their values. Some CSS properties have hyphen in their name. You can use underscore instead of hyphen in the name of the CSS properties. For example, background-color can be written as background_color.

"},{"location":"components/html/attributes.html#attr","title":"attr","text":"

The attr attribute is used to give attributes to a component element. You can add as much as you need attributes to a component element. Element().attr('key', 'value').attr('more', 'more') can be used to set the attribute of a component element. This method takes two arguments as the key and value of the attribute.

"},{"location":"components/html/attributes.html#required","title":"required","text":"

The required attribute is used to make a input field required. Element().required can be used to make a input field required. It is just a property of the Input component element. You can use this any element that accepts the required attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#disabled","title":"disabled","text":"

The disabled attribute is used to make a input field disabled. Element().disabled can be used to make a input field disabled. It is just a property of the Input component element. You can use this any element that accepts the disabled attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#readonly","title":"readonly","text":"

The readonly attribute is used to make a input field readonly. Element().readonly can be used to make a input field readonly. It is just a property of the Input component element. You can use this any element that accepts the readonly attribute as it is defined in the BaseElement class.

"},{"location":"components/html/attributes.html#value","title":"value","text":"

The value attribute is used to set the value of a field. Element().value('something') or Element(value='something') can be used to set the value of a field. It is a method in the BaseElement class. You can use this any element that accepts the value attribute as it is defined in the BaseElement class.

"},{"location":"components/html/introduction.html","title":"HTML Components","text":""},{"location":"components/html/introduction.html#what-are-html-components","title":"What are HTML Components?","text":"

HTML components are some simple set of classes that can be used to create a HTML website fast and easily. These components are very easy to use and can be used to create a HTML website in a few lines of code. Try to create a HTML website using these components and you will see how easy it is to create a HTML website using these components. So, let's get started.

"},{"location":"components/html/introduction.html#built-in-html-components","title":"Built-in HTML Components","text":"

Html : To create the main HTML page layout.

Head : To create the head section of a html website.

Title: To describe the title of a website in the head section.

Meta : To describe all types of meta tags for SEO.

Body : To create the body structure of a html website.

Script: To load Javascript codes in fronty based website.

Style: To write custom CSS fronty.

Link : To load CSS codes in fronty based website.

Anchor : To create a anchor links in a html website.

Image : To load images in a html website.

Button : To create a button in a html website.

Input : To create a input field in a html website.

Text : To create a text in a html website.

Break : To create a break line in a html website.

Form : To create a form in a html website.

Div : To create a div in a html website.

Span : To create a span in a html website.

H1 : To create a h1 in a html website.

H2 : To create a h2 in a html website.

H3 : To create a h3 in a html website.

H4 : To create a h4 in a html website.

H5 : To create a h5 in a html website.

H6 : To create a h6 in a html website.

P : To create a p in a html website.

Ul : To create a ul in a html website.

Ol : To create a ol in a html website.

Li : To create a li in a html website.

Table : To create a table in a html website.

Tr : To create a tr in a html website.

Td : To create a td in a html website.

Th : To create a th in a html website.

Caption : To create a caption in a html website.

Thead : To create a thead in a html website.

Tbody : To create a tbody in a html website.

Tfoot : To create a tfoot in a html website.

Iframe : To create a iframe in a html website.

Audio : To create a audio in a html website.

Video : To create a video in a html website.

Source : To create a source in a html website.

Select : To create a select in a html website.

Option : To create a option in a html website.

Nav : To create a nav in a html website.

Header : To create a header in a html website.

Footer : To create a footer in a html website.

Section : To create a section in a html website.

Article : To create a article in a html website.

Aside : To create a aside in a html website.

Main : To create a main in a html website.

Figure : To create a figure in a html website.

Figcaption : To create a figcaption in a html website.

Dl : To create a dl in a html website.

Dt : To create a dt in a html website.

Dd : To create a dd in a html website.

Time : To create a time in a html website.

Mark : To create a mark in a html website.

Small : To create a small in a html website.

Strong : To create a strong in a html website.

Em : To create a em in a html website.

Code : To create a code in a html website.

Pre : To create a pre in a html website.

Blockquote : To create a blockquote in a html website.

Empty : To wrap multiple elements to return a single element.

Comment : To create a comment in a html website.

"},{"location":"components/html/introduction.html#_1","title":"Introduction","text":""},{"location":"components/js/introduction.html","title":"Javascript Components","text":""},{"location":"components/js/introduction.html#what-are-javascript-components","title":"What are Javascript Components?","text":""},{"location":"customization/customized-html.html","title":"Customizing Components","text":"

You can customize the built-in components or create your own components by subclassing the fronty.html.BaseElement class. Let's see how to create a custom component.

custom_components.py
from fronty.html import (\nBaseElement,\nText\n)\nclass CustomComponent(BaseElement):\ndef __init__(self, *children, **attributes):\nsuper().__init__('custom-component', *children, **attributes)\n# Optional attributes if you want to add any custom attributes\nself._attributes['custom-attribute'] = 'custom-value'\n# Optional children if you want to add any custom children\nself._children = [\nText('This is a custom component.'),\n]\n

Now, you can use this component in your application.

main.py
from flask import Flask # or any other framework\nfrom fronty.html import (\nHtml,\nHead,\nTitle,\nBody,\n)\nfrom custom_components import CustomComponent # import the custom component\napp = Flask(__name__)\ndef layout():\nreturn Html(\nHead(\nTitle('Custom Component')\n),\nBody(\nCustomComponent()\n)\n)\n@app.route('/')\ndef home():\nreturn layout().render()\nif __name__ == '__main__':\napp.run(debug=True)\n
"},{"location":"projects/bootstrap-integration.html","title":"Bootstrap Integration","text":"

Now, let's integrate Bootstrap into our project. We will use the Bootstrap CDN to load the Bootstrap CSS and JavaScript files.

First, we will create a new folder named components inside the project folder. Then, we will create a new component named layout.py inside the components folder.

project/components/layout.py
from fronty.html import *\ndef navbar(request, **data) -> Element:\n'''This is the navbar component'''\n# The navbar layout\n_layout = Nav(\nDiv(\nAnchor(\n'Fronty',\nhref='/',\n).class_('navbar-brand'),\nButton(\nElement('span').class_('navbar-toggler-icon'),\n).class_('navbar-toggler').attr('type', 'button').attr('data-bs-toggle', 'collapse').attr('data-bs-target', '#navbarScroll').attr('aria-controls', 'navbarScroll').attr('aria-expanded', 'false').attr('aria-label', 'Toggle navigation'),\nUl(\nLi(\nAnchor(\n'Home',\nhref='/',\n).class_('nav-link active').attr('aria-current', 'page'),\n).class_('nav-item'),\nLi(\nAnchor(\n'About',\nhref='/about',\n).class_('nav-link'),\n).class_('nav-item'),\nLi(\nAnchor(\n'More',\nhref='#',\n).class_('nav-link dropdown-toggle').attr('role', 'button').attr('data-bs-toggle', 'dropdown').attr('aria-expanded', 'false'),\nUl(\nLi(\nAnchor(\n'Action',\nhref='#',\n).class_('dropdown-item'),\n),\nLi(\nAnchor(\n'Another action',\nhref='#',\n).class_('dropdown-item'),\n),\nLi(\nElement('hr').class_('dropdown-divider'),\n),\nLi(\nAnchor(\n'Something else here',\nhref='#',\n).class_('dropdown-item'),\n),\n).class_('dropdown-menu'),\n).class_('nav-item dropdown'),\n).class_('navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll').attr('style', '--bs-scroll-height: 100px;'),\nForm(\nInput(\nplaceholder='Search',\naria_label='Search',\n).class_('form-control me-2').attr('type', 'search'),\nButton(\n'Search',\n).class_('btn btn-outline-success').attr('type', 'submit'),\n).class_('d-flex').attr('role', 'search'),\n).class_('container-fluid'),\n).class_('navbar navbar-expand-lg bg-body-tertiary')\nreturn _layout\ndef layout(request, **data) -> Html:\n'''This is the layout component'''\n# The main layout\nreturn Html(\nHead(\nTitle('Fronty'),  # Page title\nMeta(charset='utf-8'),  # Character encoding\n# Responsive design\nMeta(name='viewport', content='width=device-width, initial-scale=1'),\n# Bootstrap CSS\nLink(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css',\nintegrity='sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD', crossorigin='anonymous'),\n),\nBody(\n# Navbar\nnavbar(request),\n# Main area of the page\n# The main area of the page is passed as a parameter to the layout component.\n# Get subcomponent from data or use default value\ndata.get('content', 'Empty content'),\n# Bootstrap JS\nScript(src='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js\", integrity=\"sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN', crossorigin='anonymous'),\n),\n)\n

Now, we will create a index.py file inside the components folder. This file will contain the home page component.

project/components/index.py
from fronty.html import (\nElement,\nDiv,\nH1,\nText,\nBreak\n)\n# components\nfrom components.layout import layout\ndef home(request, **data) -> Element:\n'''This is the home page component'''\n_layout = layout(\nrequest=request,\ncontent=Div(\nH1('Home'),\nText(\nf\"\"\"\n                    Path: {request.path}\n{Break()}\n                    Method: {request.method}\n                \"\"\"\n),\n).class_('container text-center')\n)\nreturn _layout\n# We have added the about inside the index.py file for simplicity.\n# You can create a new file for the about page component.\ndef about(request, **data) -> Element:\n'''This is the about page component'''\n_layout = layout(\nrequest=request,\ncontent=Div(\nH1('About'),\n).class_('container text-center')\n)\nreturn _layout\n

Now, we will update the app.py file to use the new components.

project/app.py
from flask import Flask, request\nfrom fronty.html import *\n# components\nfrom components.index import home, about\napp = Flask(__name__)\n@app.route('/')\ndef index():\n'''This is the home page view function'''\nreturn home(\nrequest=request,\ntitle='A simple framework to build a website only with Python.',\n).render()\n@app.route('/about')\ndef about_view():\n'''This is the about page view function'''\nreturn about(\nrequest=request,\ntitle='A simple framework to build a website only with Python.',\n).render()\nif __name__ == '__main__':\napp.run(debug=True)\n

Now, we will run the project and open the home page in the browser.

python project/app.py\n

Visit http://127.0.0.1:5000 in your browser.

Project URL: Bootstrap Integration

"},{"location":"projects/custom-css-project.html","title":"Custom CSS Project","text":"

Initially, we have created a basic HTML only project. Then we have integrated Bootstrap into our project. Now, we will create a custom CSS project. We will use only Python to create this project.

Let's create a new project directory named custom_css_project. Then create a new file named app.py inside the custom_css_project directory.

Now, we will create everything in side the app.py file.

custom_css_project/app.py
from flask import Flask\nfrom fronty.html import *\nfrom fronty.css import *\nfrom datetime import date\n# CSS components\ndef style_css():\n'''This is the style component'''\n# The CSS() is used to create a CSS object.\nreturn CSS(\n# The Selector() is used to create a CSS selector.\n# Here we have used the universal selector to select all the elements.\n# *{} means select all the elements.\n# We have css properties inside the properties() method.\n# Passed the css properties as keyword arguments.\n# The properties() method returns a CSSProperties object.\nSelector('*').properties({\n'margin': '0',\n'padding': '0',\n'font-family': 'Roboto, sans-serif, Arial',\n}),\n# Here we have selected the body tag.\n# We have used the Selector('body') to select the body tag.\n# Selector('body').properties({}) is used to add css properties to the body tag.\nSelector('body').properties({\n'background-color': '#d6d6e7',\n}),\nSelector('nav').properties({\n'background-color': '#484c7a',\n'color': '#fff',\n'padding': '20px',\n'position': 'absolute',\n'width': '80%',\n'margin': '0 10%',\n'top': '10px',\n'border-radius': '12px'\n}),\nSelector('nav ul').properties({\n'list-style': 'none',\n'display': 'flex',\n'flex-direction': 'row',\n'justify-content': 'center',\n}),\nSelector('nav ul li').properties({\n'margin': '0 10px'\n}),\nSelector('a').properties({\n'text-decoration': 'none',\n'color': '#fff',\n'padding': '12px',\n'border-radius': '12px',\n'transition': 'all 0.3s ease-in-out',\n'font-size': '18px',\n}),\nSelector('nav a:hover').properties({\n'background-color': '#ddd',\n'color': 'black',\n}),\nSelector('nav a:active').properties({\n'background-color': '#4CAF50',\n'color': 'white',\n}),\nSelector('.container').properties({\n'margin': '90px 10%',\n'width': '80%',\n'text-align': 'center',\n'padding': '20px',\n'background-color': '#fff',\n'border-radius': '12px',\n}),\nSelector('footer').properties({\n'position': 'absolute',\n'bottom': '10px',\n'width': '80%',\n'margin': '0 10%',\n'border-radius': '12px',\n'text-align': 'center',\n'padding': '20px',\n'background-color': '#484c7a',\n'color': '#fff',\n'font-size': '12px',\n}),\n)\n# Fronty components\ndef layout(request, **data):\n'''This is the layout component'''\n# The Html() is used to create a HTML object.\nreturn Html(\nHead(\nTitle('Custom CSS Project'),\nMeta(charset='UTF-8'),\nMeta(content=\"IE=edge\").attr('http-equiv', 'X-UA-Compatible'),\nMeta(name='viewport', content='width=device-width, initial-scale=1.0'),\nStyle(\nstyle_css().render(),\n),\n),\nBody(\nNav(\nUl(\nLi(\nAnchor('Home', href='/'),\n),\nLi(\nAnchor('About', href='/about'),\n)\n)\n),\nDiv(\nH1(\n'Custom CSS Project',\n),\nText(\n'This is a custom CSS project using Fronty.',\n),\n).class_('container'),\nFooter(\nf'\u00a9 {date.today().year} Fronty',\n),\n)\n)\napp = Flask(__name__)\n@app.route('/')\ndef home():\n'''This is the home page view function'''\n# The render() method is used to convert the python objects to HTML string.\nreturn layout(\nrequest=None,\n).render()\nif __name__ == '__main__':\napp.run(debug=True)\n
"},{"location":"projects/starter-project.html","title":"Starter Project","text":"

For simplicity, we have created a starter project that you can use to get started with your own project. It is a simple project that contains a single page with a single component. It is a good starting point for your own project.

starter_project/app.py
from flask import Flask, request\nfrom fronty.html import *\napp = Flask(__name__)\ndef home(request) -> Html:\n'''This is the home page view function'''\n# The main HTML element.\nreturn Html(\n# The head tag contains the title and meta tags.\nHead(\n# The title tag contains the title of the page.\nTitle('Home'),\n# The meta tags contain the meta information of the page.\nMeta(charset='utf-8'),\nMeta(name='viewport', content='width=device-width, initial-scale=1'),\n),\n# The body tag contains all the content of the page.\nBody(\n# The center tag contains the main content of the page.\n# It is like using a HTML element when you don't know whats the name of a tag in fronty.\n# You can use the Element('tag') for this purpose.\nElement(\n'center',\n# The h1 tag contains the title of the page.\nH1(\n'Welcome to Fronty!'\n),\n# The Text() is used to add text to the page like paragraphs.\nText(\n'Fronty is a frontend web framework.'\n),\n)\n)\n)\n@app.route('/')\ndef index() -> str:\n'''This is the home page view function'''\n# The render() method is used to convert the python objects to HTML string.\n# The render() method returns a string. So, we can return it directly.\nreturn home(\nrequest=request,\n).render()\nif __name__ == '__main__':\n# Run the app in debug mode.\n# Learn more about Flask at https://flask.palletsprojects.com/en/2.1.x/\napp.run(debug=True)\n
"},{"location":"widgets/attributes.html","title":"Attributes","text":""},{"location":"widgets/attributes.html#attributes-of-widgets","title":"Attributes of widgets","text":"

All widgets have some attributes that can be used to customize the widget. The attributes are:

"},{"location":"widgets/attributes.html#load_css","title":"load_css","text":"

This attribute is used to load the CSS of the widget. It is a boolean value. If it is True, the CSS of the widget will be loaded. If it is False, the CSS of the widget will not be loaded. The default value is False. If you need to add the CSS of the widget, you can add it manually. FormWidget(load_css=True) will load the CSS of the FormWidget widget.

"},{"location":"widgets/attributes.html#forms_type","title":"forms_type","text":"

This attribute is used to set the type of the form. It is a string value. The default value is loginform. Currently, we are working on loginform, registrationform, contactform, searchform, subscribeform and commentform. More will come soon. FormWidget(forms_type=\"loginform\") will set the type of the form to loginform.

"},{"location":"widgets/attributes.html#action","title":"action","text":"

This attribute is used to set the action of the form. It is a string value. The default value is #. FormWidget(action=\"/login\") will set the action of the form to /login. If you need to set the action of the form to the current page, you can set it to \"\" or #.

"},{"location":"widgets/attributes.html#method","title":"method","text":"

This attribute is used to set the method of the form. It is a string value. The default value is POST. FormWidget(method=\"GET\") will set the method of the form to GET.

"},{"location":"widgets/attributes.html#add_element","title":"add_element","text":"

This attribute is used to add more elements to the form. You can use it FormWidget().add_element(element) to add an element to the form. FormWidget().add_element(Input(type=\"text\", name=\"username\")) will add an input element to the form.

"},{"location":"widgets/introduction.html","title":"Widgets Introduction","text":""},{"location":"widgets/introduction.html#what-is-a-widget","title":"What is a widget?","text":"

A widget is a set of components that can be used to build a user interface (UI) smoothly and very quickly. Widgets are build for making development process easier and faster. Widgets are also used to make the UI more beautiful and attractive with a single line of code.

"},{"location":"widgets/introduction.html#how-to-use-a-widget","title":"How to use a widget?","text":"

To use a widget, you need to import it from the fronty.html.widgets module. For example, if you need to make a login form, you can use the FormWidget widget. You can simply call the FormWidget class and add it to your page.

main.py
from fronty.html.widgets import FormWidget\nfrom fronty.html import *\nfrom flask import Flask\napp = Flask(__name__)\n@app.route(\"/\")\ndef login():\nreturn Html(\nHead(\nMeta(charset=\"utf-8\"),\nTitle(\"Test case\"),\n),\nBody(\nFormWidget(load_css=True)\n)\n).render()\nif __name__ == \"__main__\":\napp.run(debug=True)\n
"}]} \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml deleted file mode 100644 index 8b7686b..0000000 --- a/docs/sitemap.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - https://almas-ali.github.io/fronty/index.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/contribution.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/examples.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/installation.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/quick-start.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/blog/index.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/introduction.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/css/attributes.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/css/introduction.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/html/attributes.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/html/introduction.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/components/js/introduction.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/customization/customized-html.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/projects/bootstrap-integration.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/projects/custom-css-project.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/projects/starter-project.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/widgets/attributes.html - 2023-05-29 - daily - - - https://almas-ali.github.io/fronty/widgets/introduction.html - 2023-05-29 - daily - - \ No newline at end of file diff --git a/docs/sitemap.xml.gz b/docs/sitemap.xml.gz deleted file mode 100644 index b9f8035..0000000 Binary files a/docs/sitemap.xml.gz and /dev/null differ diff --git a/docs/theme/announce.html b/docs/theme/announce.html deleted file mode 100644 index 997f870..0000000 --- a/docs/theme/announce.html +++ /dev/null @@ -1,3 +0,0 @@ - - -Fronty is ready to rock and roll! Try it out, and let us know what you think. \ No newline at end of file diff --git a/docs/theme/main.html b/docs/theme/main.html deleted file mode 100644 index 41af1c4..0000000 --- a/docs/theme/main.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "base.html" %} - -{% block announce %} - {% include 'announce.html' ignore missing %} -{% endblock %} - -{% block content %} - {{ super() }} - -{% endblock %} \ No newline at end of file diff --git a/docs/widgets/attributes.html b/docs/widgets/attributes.html deleted file mode 100644 index f8ad698..0000000 --- a/docs/widgets/attributes.html +++ /dev/null @@ -1,1059 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Attributes - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Attributes

-

Attributes of widgets

-

All widgets have some attributes that can be used to customize the widget. The attributes are:

-

load_css

-

This attribute is used to load the CSS of the widget. It is a boolean value. If it is True, the CSS of the widget will be loaded. If it is False, the CSS of the widget will not be loaded. The default value is False. If you need to add the CSS of the widget, you can add it manually. FormWidget(load_css=True) will load the CSS of the FormWidget widget.

-

forms_type

-

This attribute is used to set the type of the form. It is a string value. The default value is loginform. Currently, we are working on loginform, registrationform, contactform, searchform, subscribeform and commentform. More will come soon. FormWidget(forms_type="loginform") will set the type of the form to loginform.

-

action

-

This attribute is used to set the action of the form. It is a string value. The default value is #. FormWidget(action="/login") will set the action of the form to /login. If you need to set the action of the form to the current page, you can set it to "" or #.

-

method

-

This attribute is used to set the method of the form. It is a string value. The default value is POST. FormWidget(method="GET") will set the method of the form to GET.

-

add_element

-

This attribute is used to add more elements to the form. You can use it FormWidget().add_element(element) to add an element to the form. FormWidget().add_element(Input(type="text", name="username")) will add an input element to the form.

- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs/widgets/introduction.html b/docs/widgets/introduction.html deleted file mode 100644 index 2ed2a61..0000000 --- a/docs/widgets/introduction.html +++ /dev/null @@ -1,1027 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Introduction - Fronty - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - -
- - -
- -
- - - - - - -
-
- - - -
-
-
- - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - - -

Widgets Introduction

-

What is a widget?

-

A widget is a set of components that can be used to build a user interface (UI) smoothly and very quickly. Widgets are build for making development process easier and faster. Widgets are also used to make the UI more beautiful and attractive with a single line of code.

-

How to use a widget?

-

To use a widget, you need to import it from the fronty.html.widgets module. For example, if you need to make a login form, you can use the FormWidget widget. You can simply call the FormWidget class and add it to your page.

-
main.py
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
from fronty.html.widgets import FormWidget
-from fronty.html import *
-
-from flask import Flask
-
-app = Flask(__name__)
-
-@app.route("/")
-def login():
-   return Html(
-        Head(
-            Meta(charset="utf-8"),
-            Title("Test case"),
-        ),
-        Body(
-            FormWidget(load_css=True)
-        )
-    ).render()
-
-
-if __name__ == "__main__":
-    app.run(debug=True)
-
- - - - - - - - - - -
-
- - - - -
- - - -
- -
- - -
- -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/docs_src/docs/components/introduction.md b/docs_src/docs/components/introduction.md index 918328d..6c091b5 100644 --- a/docs_src/docs/components/introduction.md +++ b/docs_src/docs/components/introduction.md @@ -2,18 +2,12 @@ ## What are Components? -Components are the building blocks of your application. They are reusable UI elements that can be composed together to build a UI. Components are also the unit of encapsulation for the UI, CSS, and behavior. Components for manipulating HTML, CSS, and JavaScript from Python code are provided by the `fronty` package. Components are created by subclassing the `fronty.html.BaseElement` class. We will learn more about components in the customizing components section. +Components are the building blocks of your application. They are reusable UI elements that can be composed together to build a UI. Components are also the unit of encapsulation for the UI, CSS, and behavior. Components for manipulating HTML, CSS, and JavaScript from Python code are provided by the `fronty` package. Components are created by subclassing the `BaseElement` class in every modules. There are available `BaseElement` for HTML elements, CSS, and JavaScript. We will learn more about components in the [customizing components](../customization/introduction.md) ## Built-in Components Fronty provides a set of built-in components that can be used to create a UI. These components are: - - - - - -### For JavaScript - -Till now, there is no built-in component for JavaScript. But you can use the `Script` component to load JavaScript codes in your website from js file. - +- [HTML Components](./html/introduction.md) +- [CSS Components](./css/introduction.md) +- [Javascript Components](./js/introduction.md) diff --git a/docs_src/docs/components/js/introduction.md b/docs_src/docs/components/js/introduction.md index 1baa4df..cc3572d 100644 --- a/docs_src/docs/components/js/introduction.md +++ b/docs_src/docs/components/js/introduction.md @@ -1,3 +1,8 @@ # Javascript Components ## What are Javascript Components? + +Javascript components are the simple implementation of Javascript code that can be used to create a reusable component. These components can be used to create a reusable code that can be used in multiple places in the application. It is very easy to create a Javascript component and use it in the application. You can easily implement some of the common functionalities in the Javascript component and use it in the application. We are currently have some very basic components which we are planning to expand in the future. + +## How to use Javascript Components? + diff --git a/docs_src/docs/customization/customized-css.md b/docs_src/docs/customization/customized-css.md new file mode 100644 index 0000000..d220605 --- /dev/null +++ b/docs_src/docs/customization/customized-css.md @@ -0,0 +1 @@ +# Customizing CSS Components diff --git a/docs_src/docs/customization/customized-js.md b/docs_src/docs/customization/customized-js.md new file mode 100644 index 0000000..e6d1075 --- /dev/null +++ b/docs_src/docs/customization/customized-js.md @@ -0,0 +1 @@ +# Customizing JavaScript Components diff --git a/docs_src/docs/customization/introduction.md b/docs_src/docs/customization/introduction.md new file mode 100644 index 0000000..f6a26ce --- /dev/null +++ b/docs_src/docs/customization/introduction.md @@ -0,0 +1,15 @@ +# Customization of the components + +## What is Customization? + +When we talk about customization, we are talking about the ability to change the behavior of the components. This can be done by changing the default behavior of the components or by adding new behavior to the components. This can be done by creating a new component or by extending the existing component. + +## How to Customize Components? + +Customization of the components can be done by creating a new component or by extending the existing component. The new component can be created by subclassing the `BaseElement` class and adding the new behavior to the component. The existing component can be extended by subclassing the existing component and adding the new behavior to the component. + +We will see how to create a new component and how to extend the existing component in the following sections. + +- [HTML Customization](./customized-html.md) +- [CSS Customization](./customized-css.md) +- [Javascript Customization](./customized-js.md) diff --git a/docs_src/docs/theme/main.html b/docs_src/docs/theme/main.html index 41af1c4..db07bc3 100644 --- a/docs_src/docs/theme/main.html +++ b/docs_src/docs/theme/main.html @@ -1,10 +1,12 @@ {% extends "base.html" %} - + {% block announce %} {% include 'announce.html' ignore missing %} {% endblock %} - -{% block content %} - {{ super() }} - -{% endblock %} \ No newline at end of file + +{% block outdated %} + You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} diff --git a/docs_src/mkdocs.yml b/docs_src/mkdocs.yml index 36070bf..c003019 100644 --- a/docs_src/mkdocs.yml +++ b/docs_src/mkdocs.yml @@ -45,6 +45,9 @@ extra: provider: google property: G-XJC75ENC9N + version: + provider: mike + social: - icon: fontawesome/brands/github-alt link: https://github.com/Almas-Ali/fronty @@ -58,7 +61,7 @@ extra: - icon: fontawesome/solid/globe link: https://almasali.net - generator: false + generator: true copyright: Build with love for the community © 2023 @@ -72,16 +75,19 @@ nav: - Quick Start: quick-start.md - Components: - Introduction: components/introduction.md - - HTML: + - HTML Components: - Introduction: components/html/introduction.md - Attributes: components/html/attributes.md - - CSS: + - CSS Components: - Introduction: components/css/introduction.md - Attributes: components/css/attributes.md - - JavaScript: + - JavaScript Components: - Introduction: components/js/introduction.md - Customization: + - Introduction: customization/introduction.md - HTML Customization: customization/customized-html.md + - CSS Customization: customization/customized-css.md + - JavaScript Customization: customization/customized-js.md - Widgets: - Introduction: widgets/introduction.md - Attributes: widgets/attributes.md diff --git a/examples/Action button/app.py b/examples/Action button/app.py new file mode 100644 index 0000000..db6e085 --- /dev/null +++ b/examples/Action button/app.py @@ -0,0 +1,103 @@ +from fronty.html import widgets +from fronty import ( + html, + css, + js +) + +import flask + +app = flask.Flask(__name__) + + +@app.route('/') +def page(): + def button_event_1(event, id): + return js.Event(event, id=id) + + return html.Html( + html.Head( + html.Title('Action button'), + html.Style( + css.Selector('button').properties({ + 'padding': '10px', + 'margin': '10px', + 'font-size': '20px', + 'cursor': 'pointer', + 'background-color': 'lightblue', + 'color': '#000', + 'border': 'none', + 'border-radius': '5px', + }), + css.Selector('button:hover').properties({ + 'background-color': 'lightgreen', + }), + css.Selector('.theme').properties({ + 'background-color': '#f0f0f0', + 'color': '#000', + }), + ), + ), + html.Body( + html.Div( + html.Button('Click me', id='button1', + onclick="alert('Button clicked');"), + html.Button('Python Click me', id='button2', + onclick=js.Alert('Python Alert')), + # html.Button('Python Click me', id='button3', onclick=js.Event('click', id='button3')), + # html.Button('Python Click me', id='button4', onclick=button_event_1('click', 'button4')), + js.ConsoleLog('Hello world').script_wrap(), + html.Button('Console log click', id='button5', + onclick=js.ConsoleLog('Python Console Log')), + + js.Function('squreNumber', ['x'], + js.ConsoleLog('x')).script_wrap(), + js.SetTimeout('squreNumber(4)', 1000).script_wrap(), + ), + ) + ).render() + + +@app.route("/login", methods=['GET', 'POST']) +def login(): + if flask.request.method == 'POST': + print(flask.request.form) + # print(widgets.FormWidget.get_form_data(flask.request.form)) + + return html.Html( + html.Head( + html.Meta(charset="utf-8"), + html.Title("Test case"), + ), + html.Body( + widgets.FormWidget( + load_css=True, + method='POST', + action='/login', + ).add_element( + html.Div( + html.Label('Mobile number') + .attr('for', 'mobile'), + html.Input( + type='phone', + name='mobile', + required="", + placeholder='Enter your mobile number', + ) + .style(**{ + 'width': '100%', + 'padding': '12px 20px', + 'margin': '8px 0', + 'display': 'inline-block', + 'border': '1px solid #ccc', + 'box-sizing': 'border-box', + }), + ), + first=True + ) + ) + ).render() + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/fronty/__init__.py b/fronty/__init__.py index a396ced..1590db1 100644 --- a/fronty/__init__.py +++ b/fronty/__init__.py @@ -1,4 +1,4 @@ -__version__ = '0.0.3' +__version__ = '0.0.6' class Fronty: def __init__(self, file_path: str) -> None: diff --git a/fronty/css/__init__.py b/fronty/css/__init__.py index 179e8ba..9eb5333 100644 --- a/fronty/css/__init__.py +++ b/fronty/css/__init__.py @@ -3,7 +3,7 @@ def __init__(self, css): self.css = css def __str__(self): - return '' + return self.render() def __add__(self, other): return BaseCSS(self.css + other.css) @@ -12,7 +12,7 @@ def __radd__(self, other): return BaseCSS(other.css + self.css) def __repr__(self): - return f'' + return f'' def __call__(self): return self diff --git a/fronty/html/__init__.py b/fronty/html/__init__.py index bab3117..b678e13 100644 --- a/fronty/html/__init__.py +++ b/fronty/html/__init__.py @@ -1,3 +1,6 @@ +from typing import Union + + class BaseElement: '''Base element.''' @@ -321,6 +324,12 @@ def __init__(self, *children, **attributes): self.attributes['href'] = attributes['href'] if 'href' in attributes else '' self.attributes['rel'] = 'stylesheet' if 'rel' not in attributes else attributes['rel'] + def render(self): + '''render all inner css.Selector elements''' + _styles = ''.join(child.render() for child in self.children) + _is_space = ' ' if self._render_attributes() else '' + return f'<{self.tag}{_is_space}{self._render_attributes()}>{_styles}' + class Body(BaseElement): '''Body element.''' @@ -769,3 +778,67 @@ def __add__(self, other): def __str__(self): return self.render() + + +AnyHTMLElement = Union[ + Html, + Head, + Title, + Script, + Style, + Body, + Meta, + Link, + Anchor, + Image, + Button, + Input, + Text, + Break, + Form, + Label, + Select, + Option, + Table, + Thead, + Tbody, + Tr, + Th, + Td, + H1, + H2, + H3, + H4, + H5, + H6, + Ul, + Ol, + Li, + Span, + Div, + Nav, + Footer, + Header, + Section, + Article, + Aside, + Main, + Figure, + Figcaption, + Dl, + Dt, + Dd, + Small, + Time, + Strong, + Em, + Mark, + Code, + Pre, + Blockquote, + Iframe, + Video, + Audio, + Source, + Empty, +] diff --git a/fronty/html/widgets.py b/fronty/html/widgets.py index 6f1e2cc..5cc38d2 100644 --- a/fronty/html/widgets.py +++ b/fronty/html/widgets.py @@ -129,7 +129,7 @@ def __get_loginform(self): # All styles are included here if load_css is True. html.Style( - styles.render() + styles ) if self.load_css is True else html.Style(), html.Form( @@ -197,7 +197,7 @@ def __get_registrationform(self): return html.Section( html.Style( - styles.render() + styles ) if self.load_css is True else html.Style(), html.Form( diff --git a/fronty/js/__init__.py b/fronty/js/__init__.py new file mode 100644 index 0000000..178ba28 --- /dev/null +++ b/fronty/js/__init__.py @@ -0,0 +1,118 @@ +from ..html import AnyHTMLElement + + +class BaseElement(object): + def __init__(self, **kwargs): + self.kwargs = kwargs + + def render(self): + raise NotImplementedError + + def script_wrap(self): + '''Returns the JS code wrapped in " + + def __str__(self): + return self.render() + + def __repr__(self): + return self.render() + + def __add__(self, other): + return self.render() + other.render() + + def __radd__(self, other): + return other.render() + self.render() + + def __iadd__(self, other): + return self.render() + other.render() + + def __eq__(self, other): + return self.render() == other.render() + + def __ne__(self, other): + return self.render() != other.render() + + def __lt__(self, other): + return self.render() < other.render() + + def __le__(self, other): + return self.render() <= other.render() + + def __gt__(self, other): + return self.render() > other.render() + + def __ge__(self, other): + return self.render() >= other.render() + + def __len__(self): + return len(self.render()) + + +class Alert(BaseElement): + def __init__(self, message): + super().__init__() + self.message = message + + def render(self): + return f"alert('{self.message}');" + + +class Event(BaseElement): + def __init__(self, event, **kwargs): + super().__init__(**kwargs) + self.event = event + + def render(self): + return f"document.getElementById('{self.kwargs.get('id')}').{self.event}();" if 'id' in self.kwargs else f"document.{self.event}();" + + +class ConsoleLog(BaseElement): + def __init__(self, message): + super().__init__() + self.message = message + + def render(self): + return f"console.log('{self.message}');" + + +class Function(BaseElement): + def __init__(self, name, args: list, body: str): + super().__init__() + self.name = name + self.args = args + self.body = body + + def render(self): + return f"function {self.name}({', '.join(self.args)}){{ {self.body} }};" + + +class SetTimeout(BaseElement): + def __init__(self, function, time): + super().__init__() + self.function = function + self.time = time + + def render(self): + return f"setTimeout({self.function}, {self.time});" + + +class SetInterval(BaseElement): + def __init__(self, function, time: int): + super().__init__() + self.function = function + self.time = time + + def render(self): + return f"setInterval({self.function}, {self.time});" + + +class ToggleClass(BaseElement): + def __init__(self, html: AnyHTMLElement, class1: str, class2: str): + super().__init__() + self.html = html + self.class1 = class1 + self.class2 = class2 + + def render(self): + return self.html.class_ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..893b48c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,67 @@ +[project] +name = "fronty" +dynamic = ["version"] +dependencies = [] +requires-python = ">=3.7" +authors = [{name = "Md. Almas Ali", email = "almaspr3@gmail.com"}] +maintainers = [{name = "Md. Almas Ali", email = "almaspr3@gmail.com"}] +description = "A frontend web framework" +readme = "README.md" +license = {file = "LICENSE"} +keywords = [ + "web framework", + "frontend framework", + "frontend", + "web", + "framework", + "html", + "css", + "javascript", + "simple", + "easy", + "fast", + "lightweight", + "light", + "light-weight", + "quick", + "rapid", +] +classifiers = [ + "Topic :: Internet", + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] + + +[project.urls] +Homepage = "https://github.com/Almas-Ali/fronty" +Documentation = "https://github.com/Almas-Ali/fronty#readme" +Repository = "https://github.com/Almas-Ali/fronty" +"Bug Tracker" = "https://github.com/Almas-Ali/fronty/issues" + + +[project.scripts] +fronty = "fronty.cli:main" + + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + + +[tool.hatch.version] +path = "fronty/__init__.py" + + +[tool.ruff.format] +quote-style = "single" diff --git a/setup.py b/setup.py deleted file mode 100644 index 9245809..0000000 --- a/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -from setuptools import setup, find_packages - -with open('README.md', 'r') as f: - long_description = f.read() - -setup( - name='fronty', - version='0.0.5', - description='A frontend web framework', - long_description_content_type='text/markdown', - long_description=long_description, - author='Almas Ali', - author_email='almaspr3@gmail.com', - url='https://github.com/Almas-Ali/fronty', - packages=find_packages(), - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.7', - ], - keywords='web framework', - python_requires='>=3.7', - - entry_points={ - 'console_scripts': [ - 'fronty=fronty.cli:main', - ], - }, -)