UNPKG

gsheetcmslight

Version:

A library to read a Google Sheet with multilingal content

3 lines 16.7 kB
/*! gsheetcmslight v1.1.0 | (c) 2020 | GPL-3.0-or-later License | git+https://github.com/Puzzlout/GoogleSheetCmsLight.git */ /*! gsheetcmslight v1.1.0 | (c) 2020 | GPL-3.0-or-later License | git+https://github.com/Puzzlout/GoogleSheetCmsLight.git */ var ConvertionUtility=function(){this.SEPERATOR=","};ConvertionUtility.prototype={CheckAndReturnString:function(e){if("string"==typeof e)return e},ParseValueAsArray:function(e){if(-1!==e.indexOf(this.SEPERATOR))return e.split(this.SEPERATOR).map(e=>e.trim());console.warn(`Value ${e} doesn't contain the seperator ${this.SEPERATOR}`)},ParseValueAsBoolean:function(e){const t="true"===e.trim().toLowerCase(),n="false"===e.trim().toLowerCase();if(t||n)return!!t;console.warn(`Value "${e}" is not true or false`)},ParseValueAsInt:function(e){if(/^(-|\+)?(\d+|Infinity)$/.test(e))return Number(e)}},"undefined"!=typeof module&&module.exports?module.exports=ConvertionUtility:"function"==typeof define&&define.amd?define((function(){return ConvertionUtility})):window.ConvertionUtility=ConvertionUtility;var QueryStringUtility=function(e){this.enableLog=!1,void 0!==e&&void 0!==e.enableLog&&(this.enableLog=op.enableLog)};QueryStringUtility.prototype={GetValue:function(e){const t=this.GetKeyValuePairs()[e];return void 0===t&&this.enableLog&&console.warn(`Key "${e}" is not found in the query string`),t},GetKeyValuePairs:function(){const e=this.GetArray();let t=[];return e.forEach(e=>{var n=e.split("=");Object.defineProperty(t,n[0],{value:n[1]})}),t},GetArray:function(){const e=document.location.href;if(-1===e.indexOf("?"))return[];const t=e.substring(e.indexOf("?")+1,e.length);return this.enableLog&&console.log("Query is",t),t.split("&")}},"undefined"!=typeof module&&module.exports?module.exports=QueryStringUtility:"function"==typeof define&&define.amd?define((function(){return QueryStringUtility})):window.QueryStringUtility=QueryStringUtility;var BrowserLanguageParser=function(e){this.enableLog=!1,void 0!==e&&(this.enableLog=!1|e.enableLog)};BrowserLanguageParser.prototype={ReturnDefaultIfNavigatorLangsUnsupported:function(){this.enableLog&&console.log("navigator.languages not supported...")},ReturnDefaultIfNavigatorLangsUndefinedOrNull:function(){this.enableLog&&console.log("navigator.languages is undefined or null...")},ReturnDefaultIfNavigatorLangsEmpty:function(){this.enableLog&&console.log("navigator.languages is empty...")},GetBrowserFirstLang:function(){return navigator.languages?void 0===navigator.languages||null===navigator.languages?this.ReturnDefaultIfNavigatorLangsUndefinedOrNull():0===navigator.languages.length?this.ReturnDefaultIfNavigatorLangsEmpty():navigator.languages[0]:this.ReturnDefaultIfNavigatorLangsUnsupported()}},"undefined"!=typeof module&&module.exports?module.exports=BrowserLanguageParser:"function"==typeof define&&define.amd?define((function(){return BrowserLanguageParser})):window.BrowserLanguageParser=BrowserLanguageParser;var SheetValidator=function(e){if(this.CheckI8n=!0,void 0!==e){if(void 0!==e.checkI8n&&(this.CheckI8n=e.checkI8n),void 0===e.sheet)throw new Error("Sheet is absent");if(e.sheet==={})throw new Error("Sheet is empty");if(0===Object.keys(e.sheet).length)throw new Error("Sheet has not properties");if(void 0===e.sheet.columnNames)throw new Error("Sheet column names is not set");if(0===e.sheet.columnNames.length)throw new Error("Sheet has no columns");this.ColumnNames=e.sheet.columnNames,this.Config=e.config,this.DEFAULT_COLUMN_NAME="Value"}};SheetValidator.prototype={RetrieveBrowserLang:function(){return new BrowserLanguageParser({enableLog:this.enableLog}).GetBrowserFirstLang()},RetrieveRequestLang:function(){return new QueryStringUtility({enableLog:this.enableLog}).GetValue("lang")},GetUsedLanguage:function(){const e=this.RetrieveBrowserLang(),t=this.RetrieveRequestLang(),n=this.Config.DefaultLanguage;return void 0===n&&void 0===e&&void 0===t&&this.enableLog&&console.warn("No language found in the Google Sheet or the Browser."),void 0!==t?(this.SetDocumentLang(t),t):void 0!==e?(this.SetDocumentLang(e),e):void 0!==n?(this.SetDocumentLang(n),configLang):void 0},SetDocumentLang:function(e){document.querySelector("html").lang=e},BuildExpectedI8nColumnName:function(){const e=this.GetUsedLanguage();return`${this.DEFAULT_COLUMN_NAME}_${e}`},GetDefaultColumnValueName:function(){return this.DEFAULT_COLUMN_NAME},GetI8nColumnExistsForUserLanguage:function(){const e=this.BuildExpectedI8nColumnName();return this.GetColumnName(this.ColumnNames,e)},GetValueColumnIdentity:function(e){if(!this.CheckI8n)return this.DEFAULT_COLUMN_NAME;const t=this.GetI8nColumnExistsForUserLanguage();if(t.isValid)return t.columnName;console.info("Falling back to default column...");const n=this.GetColumnName(this.ColumnNames,this.DEFAULT_COLUMN_NAME,!0);if(n.isValid)return n.columnName;const o=new Error(`The sheet "${e.name}" must at least contain a Value column`);throw new Error(o)},GetColumnName:function(e,t,n=!1){this.enableLog&&console.log("Row keys",e);var o=n?this.FilterKeysExactly(t,e):this.FilterKeysLoosely(t,e);return this.enableLog&&console.log("rowKeysFiltered",o),o.length>0?{isValid:!0,columnName:o[0]}:(this.enableLog&&console.log(`The sheet doesn't contain any column matching the column '${t}'`),{isValid:!1})},FilterKeysExactly:function(e,t){if(void 0===e)throw new Error("Parameter filter is required");if("string"!=typeof e)throw new Error("Parameter filter must be string");if(void 0===t)throw new Error("Parameter array is required");if(!Array.isArray(t))throw new Error("Parameter array must be array");if(0===t.length)throw new Error("Parameter array must have values");let n=[];const o=new RegExp("^"+e.toLowerCase()+"$","g");return t.reduce((e,t)=>t.toLowerCase().match(o)?n.push(t):n),n},FilterKeysLoosely:function(e,t){let n=[];return t.reduce((t,o)=>-1!=o.toLowerCase().indexOf(e.toLowerCase())?n.push(o):n),n}},"undefined"!=typeof module&&module.exports?module.exports=SheetValidator:"function"==typeof define&&define.amd?define((function(){return SheetValidator})):window.SheetValidator=SheetValidator;var DataTransformer=function(e){if(void 0===e)throw new Error("options must be present");if(void 0===e.config)throw new Error("options must contains a config object");if(void 0===e.config.GoogleSheetsCmsVersion)throw new Error("options.config must contain at least the version (GoogleSheetsCmsVersion)");if(void 0===e.config.DefaultLanguage)throw new Error("options.config must contain the default language (DefaultLanguage)");this.Config=e.config,this.enableLog=!1|e.enableLog};DataTransformer.prototype={TransformSheetData:function(e,t){if("ignore"===t)return!1;const n=new SheetValidator({checkI8n:!0,sheet:e,config:this.Config}).GetValueColumnIdentity(e);return"array"===t?this.TransformDataToArray(e,n):"object"===t?this.TransformDataToObject(e,n):"nestedObject"===t?this.TransformDataToNestedObject(e,n):(console.warn("Type "+t+" is not implemented at the moment. "),void console.warn("Sheet '"+e.name+"' will be ignored."))},TransformDataToNestedObject:function(e,t){const n=this;var o=[];return e.elements.forEach((function(e){var a=e.Section;o[a]||Object.defineProperty(o,a,{value:{}}),Object.defineProperty(o[a],e.Key,{value:n.GetValueI8n(e,t)})})),o},TransformDataToArray:function(e,t){const n=this;var o=[];return e.elements.forEach((function(e){o.push({key:e.Key,value:n.GetValueI8n(e,t),href:e.Href,order:e.Order,isActive:n.GetTruthyValueFromStr(e.IsActive),openNewTab:n.GetTruthyValueFromStr(e.OpenNewTab)})})),o},TransformDataToObject:function(e,t){var n={};const o=this;return e.elements.forEach((function(e){Object.defineProperty(n,e.Key,{value:o.GetValueI8n(e,t)})})),n},GetValueI8n:function(e,t){this.enableLog&&console.log("Value column is:",t);const n=e[t];return this.enableLog&&console.log("Value read:",n),n},GetTruthyValueFromStr:function(e){return void 0!==e&&"true"===e.toLowerCase()}},"undefined"!=typeof module&&module.exports?module.exports=DataTransformer:"function"==typeof define&&define.amd?define((function(){return DataTransformer})):window.DataTransformer=DataTransformer;var SheetConfigChecker=function(e,t,n){if(""===e)throw new Error("Please provide the keyColName parameter");if(""===t)throw new Error("Please provide the valueColName parameter");if(""===n)throw new Error("Please provide the typeColName parameter");this.KeyColName=e,this.ValueColName=t,this.TypeColName=n,this.DefaultLanguageSetting="DefaultLanguage",this.SupportedLanguagesSetting="SupportedLanguages",this.UseLanguageMenuSetting="UseLanguageMenu"};SheetConfigChecker.prototype={SomeVariablesExist:function(e){return void 0!==e&&e.length>0},CheckColumnFormat:function(e,t){const n=`The ${t} colum must be named. It is empty.`,o=`The colum isn't named ${t}. It equals to "${e}".`;if(void 0===e)throw new Error(`The ${t} colum must be named. It is undefined.`);if(""===e.trim())throw new Error(n);switch(t){case this.KeyColName:if(e!==this.KeyColName)throw new Error(o);break;case this.ValueColName:if(e!==this.ValueColName)throw new Error(o);break;case this.TypeColName:if(e!==this.TypeColName)throw new Error(o);break;default:throw new Error("whichColumn parameter isn't right...")}},CheckSettingPart:function(e,t,n){const o=`The ${n} in row ${t} is empty.`;return!(""===e.trim())||(console.warn(o),!1)},CheckIntegrity:function(e){this.CheckSupportedLanguagesSetting(e),this.CheckUseLanguageMenuSetting(e)},CheckUseLanguageMenuSetting:function(e){if(e[this.UseLanguageMenuSetting]){if(!(void 0!==e[this.SupportedLanguagesSetting]))throw new Error("SupportedLanguages must be set if UseLanguageMenu is TRUE")}},CheckSupportedLanguagesSetting:function(e){if(e[this.SupportedLanguagesSetting]){const t=e[this.UseLanguageMenuSetting];if(!(void 0!==t))return void console.warn("UseLanguageMenu must be set to use SupportedLanguages");t||console.warn("UseLanguageMenu must be TRUE to use SupportedLanguages")}}},"undefined"!=typeof module&&module.exports?module.exports=SheetConfigChecker:"function"==typeof define&&define.amd?define((function(){return SheetConfigChecker})):window.SheetConfigChecker=SheetConfigChecker;var SheetConfigReader=function(e){if(void 0===e)throw new Error("options must contains sheetUrl");if(void 0===e.sourceData)throw new Error("options must contains raw data of the configuration sheet");this.SourceData=e.sourceData,this.enableLog=!1|e.enableLog,this.COLUMN_KEY="Key",this.COLUMN_VALUE="Value",this.COLUMN_TYPE="Type"};SheetConfigReader.prototype={GetConfig:function(){this.enableLog&&console.log(this.SourceData);const e=new SheetConfigChecker(this.COLUMN_KEY,this.COLUMN_VALUE,this.COLUMN_TYPE),t=this.SourceData.columnNames[0];e.CheckColumnFormat(t,this.COLUMN_KEY);const n=this.SourceData.columnNames[1];e.CheckColumnFormat(n,this.COLUMN_VALUE);const o=this.SourceData.columnNames[2];if(e.CheckColumnFormat(o,this.COLUMN_TYPE),!e.SomeVariablesExist(this.SourceData.elements))return{};let a={},i=2;return this.SourceData.elements.forEach(t=>{this.ParseVariable(a,t,i,e),i+=1}),this.enableLog&&console.log("Config",a),e.CheckIntegrity(a),a},ParseVariable:function(e,t,n,o){let a=t[this.COLUMN_KEY];const i=o.CheckSettingPart(a,n,this.COLUMN_KEY);let r=t[this.COLUMN_VALUE];const s=o.CheckSettingPart(r,n,this.COLUMN_VALUE);let u=t[this.COLUMN_TYPE];const l=o.CheckSettingPart(u,n,this.COLUMN_TYPE),h=this.ParseValueAsType(r,u);i&&s&&l&&void 0!==h&&Object.defineProperty(e,a,{value:h})},ParseValueAsType:function(e,t){const n=new ConvertionUtility;switch(t){case"string":return n.CheckAndReturnString(e);case"array":return n.ParseValueAsArray(e);case"boolean":return n.ParseValueAsBoolean(e);case"int":return n.ParseValueAsInt(e);default:return void console.warn(`The type ${t} is not implemented.`)}}},"undefined"!=typeof module&&module.exports?module.exports=SheetConfigReader:"function"==typeof define&&define.amd?define((function(){return SheetConfigReader})):window.SheetConfigReader=SheetConfigReader;var GoogleSheetReader=function(e){if("undefined"===e)throw new Error("options must contains sheetUrl");this.sheetUrl=e.sheetUrl,this.enableLog=!1|e.enableLog,this.config={},this.SHEET_DATATYPE="Sheet_DataType",this.SHEET_CONFIGURATION="Configuration"};GoogleSheetReader.prototype={CheckSheetTypeExists:function(e){if(void 0===e.models[this.SHEET_DATATYPE]){const e="Please create a sheet 'Sheet_DataType' to define how should be transformed each sheet data";throw alert(e),new Error(e)}},CheckSheetType:function(e,t){if(void 0===e[t]){const e="Please add "+t+" in sheet 'Sheet_DataType' to define how it should be transformed from the Google Sheet document";throw alert(e),new Error(e)}},LoadConfig:function(e){this.config=new SheetConfigReader({sourceData:e.models[this.SHEET_CONFIGURATION],enableLog:this.enableLog}).GetConfig()},GetData:function(){return self=this,new Promise((function(e,t){var n={key:self.sheetUrl,callback:function(t,n){return void e(n)},simpleSheet:!0};Tabletop.init(n)}))},TransformData:function(e){this.enableLog&&console.log(e),this.CheckSheetTypeExists(e);const t=this;let n={};return this.LoadConfig(e),e.modelNames.forEach((function(o){t.TransformCurrentSheetData(e,o,n)})),this.enableLog&&console.log("Formatted data",n),n},TransformCurrentSheetData:function(e,t,n){const o={config:this.config,enableLog:this.enableLog};var a=this.GetSheetDataType(e,o);this.CheckSheetType(a,t);var i=e.models[t],r=new DataTransformer(o).TransformSheetData(i,a[t]);this.UpdateViewModel(n,t,r)},GetSheetDataType:function(e,t){return new DataTransformer(t).TransformDataToObject(e.models[this.SHEET_DATATYPE],"Value")},UpdateViewModel:function(e,t,n){n&&Object.defineProperty(e,t,{value:n})}},"undefined"!=typeof module&&module.exports?module.exports=GoogleSheetReader:"function"==typeof define&&define.amd?define((function(){return GoogleSheetReader})):window.GoogleSheetReader=GoogleSheetReader;var DomHeadUpdater=function(e){if(void 0===e)throw new Error("options must contains sheetUrl");this.enableFeature=!1,e.enableFeature&&(this.enableFeature=e.enableFeature),this.enableLog=!1,void 0!==e.enableLog&&(this.enableLog=e.enableLog),this.dataPresent=!1,e.data&&(this.dataPresent=!0),this.data=e.data,this.ATTR_TEXT="text",this.ATTR_CONTENT="content"};DomHeadUpdater.prototype={UpdateTwitterTags:function(){this.dataPresent&&(this.UpdateHeadMetaTag('meta[name="twitter:card"]',this.ATTR_CONTENT,this.data.twitterCard,"twitter:card tag is missing in head element"),this.UpdateHeadMetaTag('meta[name="twitter:site"]',this.ATTR_CONTENT,this.data.twitterSite,"twitter:site tag is missing in head element"),this.UpdateHeadMetaTag('meta[name="twitter:creator"]',this.ATTR_CONTENT,this.data.twitterCreator,"twitter:creator tag is missing in head element"),this.UpdateHeadMetaTag('meta[name="twitter:description"]',this.ATTR_CONTENT,this.data.twitterDescription,"twitter:description tag is missing in head element"),this.UpdateHeadMetaTag('meta[name="twitter:image"]',this.ATTR_CONTENT,this.data.twitterImage,"twitter:image tag is missing in head element"))},UpdateOgTags:function(){this.dataPresent&&(this.UpdateHeadMetaTag('meta[property="og:title"]',this.ATTR_CONTENT,this.data.ogTitle,"og:title tag is missing in head element"),this.UpdateHeadMetaTag('meta[property="og:description"]',this.ATTR_CONTENT,this.data.ogDescription,"og:description tag is missing in head element"),this.UpdateHeadMetaTag('meta[property="og:url"]',this.ATTR_CONTENT,this.data.ogUrl,"og:url tag is missing in head element"),this.UpdateHeadMetaTag('meta[property="og:type"]',this.ATTR_CONTENT,this.data.ogType,"og:type tag is missing in head element"),this.UpdateHeadMetaTag('meta[property="og:image"]',this.ATTR_CONTENT,this.data.ogImage,"og:image tag is missing in head element"),this.UpdateHeadMetaTag('meta[property="og:image:alt"]',this.ATTR_CONTENT,this.data.ogImageAlt,"og:image:alt tag is missing in head element"))},UpdateGeneralTags:function(){this.dataPresent&&(this.UpdateHeadMetaTag("head title","text",this.data.title,"title tag is missing in head element"),this.UpdateHeadMetaTag('meta[name="description"]',"content",this.data.description,"description tag is missing in head element"))},UpdateHeadMetaTag:function(e,t,n,o){const a=document.querySelector(e);if(a){if(void 0===a[t])throw new Error(`"${t}" is not present from meta tag selected by "${e}""`);void 0===n&&console.error(e+" won't be updated because no value is defined in the MetaData sheet."),n&&(a[t]=n)}else console.error(o)},Run:function(){this.enableFeature&&this.dataPresent&&(this.UpdateGeneralTags(),this.UpdateTwitterTags(),this.UpdateOgTags())}},"undefined"!=typeof module&&module.exports?module.exports=DomHeadUpdater:"function"==typeof define&&define.amd?define((function(){return DomHeadUpdater})):window.DomHeadUpdater=DomHeadUpdater;