HandlebarJS sample using webpack loader configuration (#142)

* handlebarsjs webpack loader sample

* removed trashed folder
This commit is contained in:
Stefan Bauer 2017-03-07 21:57:26 +01:00 committed by Vesa Juvonen
parent 378680f1cb
commit e6afa9ad4f
33 changed files with 787 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@ -0,0 +1 @@
* text=auto

View File

@ -0,0 +1,32 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

View File

@ -0,0 +1,14 @@
# Folders
.vscode
coverage
node_modules
sharepoint
src
temp
# Files
*.csproj
.git*
.yo-rc.json
gulpfile.js
tsconfig.json

View File

@ -0,0 +1,3 @@
{
"vsicons.presets.angular": false
}

View File

@ -0,0 +1,8 @@
{
"@microsoft/generator-sharepoint": {
"libraryName": "spfx-handlebars",
"framework": "none",
"version": "1.0.0",
"libraryId": "b8285cda-e974-4141-aab6-b7927b732a41"
}
}

View File

@ -0,0 +1,45 @@
## SPFx Sample with Handlebars.js
This sample demonstrate how to set up SPFX to use [Handlebars](http://handlebarsjs.com) through [webpack loader](https://webpack.github.io/docs/loaders.html).
## Used SharePoint Framework Version
![drop](https://img.shields.io/badge/drop-GA-green.svg)
## Applies to
* [SharePoint Framework Developer](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
## Solution
Solution|Author(s)
--------|---------
SPFx-handlebars | Stefan Bauer - n8d ([@stfbauer](https://twitter.com/stfbauer))
## Version history
Version|Date|Comments
-------|----|--------
1.0|March 5, 2017|Initial release
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
### Building the code
```bash
git clone the repo
npm i
npm i -g gulp
gulp
```
This package produces the following:
* lib/* - intermediate-stage commonjs build artifacts
* dist/* - the bundled script, along with other resources
* deploy/* - all resources which should be uploaded to a CDN.

View File

@ -0,0 +1,19 @@
{
"entries": [{
"entry": "./lib/webparts/handlebarsDemo/HandlebarsDemoWebPart.js",
"manifest": "./src/webparts/handlebarsDemo/HandlebarsDemoWebPart.manifest.json",
"outputPath": "./dist/handlebars-demo.bundle.js"
}],
"externals": {
// Load Handlebar templates from CDN
// "handlebars": "https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.amd.js"
// load handlebars from node_modules
"handlebars": "./node_modules/handlebars/dist/handlebars.amd.min.js"
},
"localizedResources": {
"handlebarsDemoStrings": "webparts/handlebarsDemo/loc/{locale}.js"
}
}

View File

@ -0,0 +1,3 @@
{
"deployCdnPath": "temp/deploy"
}

View File

@ -0,0 +1,6 @@
// copy-static-assets.json
{
"includeExtensions": [
"hbs"
]
}

View File

@ -0,0 +1,6 @@
{
"workingDir": "./temp/deploy/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "spfx-handlebars",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,10 @@
{
"solution": {
"name": "spfx-handlebars-client-side-solution",
"id": "b8285cda-e974-4141-aab6-b7927b732a41",
"version": "1.0.0.0"
},
"paths": {
"zippedPackage": "solution/spfx-handlebars.sppkg"
}
}

View File

@ -0,0 +1,9 @@
{
"port": 4321,
"initialPage": "https://localhost:5432/workbench",
"https": true,
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}

View File

@ -0,0 +1,46 @@
{
// Display errors as warnings
"displayAsWarning": true,
// The TSLint task may have been configured with several custom lint rules
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
// project). If true, this flag will deactivate any of these rules.
"removeExistingRules": true,
// When true, the TSLint task is configured with some default TSLint "rules.":
"useDefaultConfigAsBase": false,
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
// which are active, other than the list of rules below.
"lintConfig": {
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-case": true,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-unused-imports": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"valid-typeof": true,
"variable-name": false,
"whitespace": false,
"prefer-const": true
}
}
}

View File

@ -0,0 +1,3 @@
{
"cdnBasePath": "<!-- PATH TO CDN -->"
}

View File

@ -0,0 +1,22 @@
'use strict';
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
// Custom config section starts here
const loaderConfig = [{
test: /\.hbs/,
loader: "handlebars-template-loader"
}];
// push loader configuration to SPFx configuration
build.configureWebpack.mergeConfig({
additionalConfiguration: (generatedConfiguration) => {
generatedConfiguration.module.loaders.push(loaderConfig);
return generatedConfiguration;
}
});
build.initialize(gulp);

View File

@ -0,0 +1,29 @@
{
"name": "spfx-handlebars",
"version": "0.0.1",
"private": true,
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"@microsoft/sp-client-base": "~1.0.0",
"@microsoft/sp-core-library": "~1.0.0",
"@microsoft/sp-webpart-base": "~1.0.0",
"@types/webpack-env": ">=1.12.1 <1.14.0",
"handlebars": "^4.0.6"
},
"devDependencies": {
"@microsoft/sp-build-web": "~1.0.0",
"@microsoft/sp-module-interfaces": "~1.0.0",
"@microsoft/sp-webpart-workbench": "~1.0.0",
"@types/chai": ">=3.4.34 <3.6.0",
"@types/mocha": ">=2.2.33 <2.6.0",
"gulp": "~3.9.1",
"handlebars-template-loader": "^0.7.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
}
}

View File

@ -0,0 +1,3 @@
{
"vsicons.presets.angular": false
}

View File

@ -0,0 +1,14 @@
<div class="{{styles.helloWorld}}">
<div class="{{styles.container}}">
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white {{styles.row}}">
<div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
<span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint!</span>
<p class="ms-font-l ms-fontColor-white">Customize SharePoint experiences using Web Parts.</p>
<p class="ms-font-l ms-fontColor-white">{{description}}</p>
<a href="https://aka.ms/spfx" class="{{styles.button}}">
<span class="{{styles.label}}">Learn more</span>
</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,52 @@
.helloWorld {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
padding: 20px;
}
.listItem {
max-width: 715px;
margin: 5px auto 5px auto;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: #0078d7;
border-color: #0078d7;
color: #ffffff;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
font-weight: 400;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
padding: 0 16px;
.label {
font-weight: 600;
font-size: 14px;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
}

View File

@ -0,0 +1,20 @@
{
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "5cf1bbfb-4088-4eb1-8221-c5ebf4e37606",
"alias": "HandlebarsDemoWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"manifestVersion": 2,
"preconfiguredEntries": [{
"groupId": "5cf1bbfb-4088-4eb1-8221-c5ebf4e37606",
"group": { "default": "Under Development" },
"title": { "default": "HandlebarsDemo" },
"description": { "default": "Handlebars Demo Web Part" },
"officeFabricIconFontName": "Page",
"properties": {
"description": "HandlebarsDemo"
}
}]
}

View File

@ -0,0 +1,59 @@
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-webpart-base';
import { escape } from '@microsoft/sp-lodash-subset';
import styles from './HandlebarsDemo.module.scss';
import * as strings from 'handlebarsDemoStrings';
import { IHandlebarsDemoWebPartProps } from './IHandlebarsDemoWebPartProps';
// Importing handlebars
import * as Handlebars from 'handlebars';
// load and precompile template
var HelloWorldTemplate = <HandlebarsTemplateDelegate>require('../../templates/HelloWorld.hbs');
export default class HandlebarsDemoWebPart extends BaseClientSideWebPart<IHandlebarsDemoWebPartProps> {
public render(): void {
// bind data to template
var data = {
styles: styles,
description: this.properties.description
}
// compile and add template
this.domElement.innerHTML = HelloWorldTemplate(data);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}

View File

@ -0,0 +1,3 @@
export interface IHandlebarsDemoWebPartProps {
description: string;
}

View File

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

View File

@ -0,0 +1,10 @@
declare interface IHandlebarsDemoStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
}
declare module 'handlebarsDemoStrings' {
const strings: IHandlebarsDemoStrings;
export = strings;
}

View File

@ -0,0 +1,9 @@
/// <reference types="mocha" />
import { assert } from 'chai';
describe('HandlebarsDemoWebPart', () => {
it('should do something', () => {
assert.ok(true);
});
});

View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"types": [
"es6-promise",
"es6-collections",
"webpack-env"
]
}
}

View File

@ -0,0 +1,5 @@
{
"globalDependencies": {
"handlebars": "registry:dt/handlebars#4.0.5+20160810231743"
}
}

View File

@ -0,0 +1,8 @@
// Type definitions for Microsoft ODSP projects
// Project: ODSP
/* Global definition for UNIT_TEST builds
Code that is wrapped inside an if(UNIT_TEST) {...}
block will not be included in the final bundle when the
--ship flag is specified */
declare const UNIT_TEST: boolean;

View File

@ -0,0 +1,291 @@
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/90198235019d12c00b3ccca03a36cc3d1579d644/handlebars/index.d.ts
declare namespace Handlebars {
export function registerHelper(name: string, fn: Function, inverse?: boolean): void;
export function registerHelper(name: Object): void;
export function registerPartial(name: string, str: any): void;
export function unregisterHelper(name: string): void;
export function unregisterPartial(name: string): void;
export function K(): void;
export function createFrame(object: any): any;
export function Exception(message: string): void;
export function log(level: number, obj: any): void;
export function parse(input: string): hbs.AST.Program;
export function compile(input: any, options?: CompileOptions): HandlebarsTemplateDelegate;
export function precompile(input: any, options?: PrecompileOptions): TemplateSpecification;
export function template(precompilation: TemplateSpecification): HandlebarsTemplateDelegate;
export function create(): typeof Handlebars;
export var SafeString: typeof hbs.SafeString;
export var escapeExpression: typeof hbs.Utils.escapeExpression;
export var Utils: typeof hbs.Utils;
export var logger: Logger;
export var templates: HandlebarsTemplates;
export var helpers: any;
export function registerDecorator(name: string, fn: Function): void;
export function registerDecorator(obj: {[name: string] : Function}): void;
export function unregisterDecorator(name: string): void;
export function noConflict(): typeof Handlebars;
export module AST {
export var helpers: hbs.AST.helpers;
}
interface ICompiler {
accept(node: hbs.AST.Node): void;
Program(program: hbs.AST.Program): void;
BlockStatement(block: hbs.AST.BlockStatement): void;
PartialStatement(partial: hbs.AST.PartialStatement): void;
PartialBlockStatement(partial: hbs.AST.PartialBlockStatement): void;
DecoratorBlock(decorator: hbs.AST.DecoratorBlock): void;
Decorator(decorator: hbs.AST.Decorator): void;
MustacheStatement(mustache: hbs.AST.MustacheStatement): void;
ContentStatement(content: hbs.AST.ContentStatement): void;
CommentStatement(comment?: hbs.AST.CommentStatement): void;
SubExpression(sexpr: hbs.AST.SubExpression): void;
PathExpression(path: hbs.AST.PathExpression): void;
StringLiteral(str: hbs.AST.StringLiteral): void;
NumberLiteral(num: hbs.AST.NumberLiteral): void;
BooleanLiteral(bool: hbs.AST.BooleanLiteral): void;
UndefinedLiteral(): void;
NullLiteral(): void;
Hash(hash: hbs.AST.Hash): void;
}
export class Visitor implements ICompiler {
accept(node: hbs.AST.Node): void;
acceptKey(node: hbs.AST.Node, name: string): void;
acceptArray(arr: hbs.AST.Expression[]): void;
Program(program: hbs.AST.Program): void;
BlockStatement(block: hbs.AST.BlockStatement): void;
PartialStatement(partial: hbs.AST.PartialStatement): void;
PartialBlockStatement(partial: hbs.AST.PartialBlockStatement): void;
DecoratorBlock(decorator: hbs.AST.DecoratorBlock): void;
Decorator(decorator: hbs.AST.Decorator): void;
MustacheStatement(mustache: hbs.AST.MustacheStatement): void;
ContentStatement(content: hbs.AST.ContentStatement): void;
CommentStatement(comment?: hbs.AST.CommentStatement): void;
SubExpression(sexpr: hbs.AST.SubExpression): void;
PathExpression(path: hbs.AST.PathExpression): void;
StringLiteral(str: hbs.AST.StringLiteral): void;
NumberLiteral(num: hbs.AST.NumberLiteral): void;
BooleanLiteral(bool: hbs.AST.BooleanLiteral): void;
UndefinedLiteral(): void;
NullLiteral(): void;
Hash(hash: hbs.AST.Hash): void;
}
}
/**
* Implement this interface on your MVW/MVVM/MVC views such as Backbone.View
**/
interface HandlebarsTemplatable {
template: HandlebarsTemplateDelegate;
}
interface HandlebarsTemplateDelegate {
(context: any, options?: any): string;
}
interface HandlebarsTemplates {
[index: string]: HandlebarsTemplateDelegate;
}
interface TemplateSpecification {
}
interface CompileOptions {
data?: boolean;
compat?: boolean;
knownHelpers?: {
helperMissing?: boolean;
blockHelperMissing?: boolean;
each?: boolean;
if?: boolean;
unless?: boolean;
with?: boolean;
log?: boolean;
lookup?: boolean;
}
knownHelpersOnly?: boolean;
noEscape?: boolean;
strict?: boolean;
assumeObjects?: boolean;
preventIndent?: boolean;
ignoreStandalone?: boolean;
explicitPartialContext?: boolean;
}
interface PrecompileOptions extends CompileOptions {
srcName?: string;
destName?: string;
}
declare namespace hbs {
class SafeString {
constructor(str: string);
static toString(): string;
}
namespace Utils {
function escapeExpression(str: string): string;
function createFrame(obj: Object): Object;
function isEmpty(obj: any) : boolean;
function extend(obj: any, ...source: any[]): any;
function toString(obj: any): string;
function isArray(obj: any): boolean;
function isFunction(obj: any): boolean;
}
}
interface Logger {
DEBUG: number;
INFO: number;
WARN: number;
ERROR: number;
level: number;
methodMap: { [level: number]: string };
log(level: number, obj: string): void;
}
declare namespace hbs {
namespace AST {
interface Node {
type: string;
loc: SourceLocation;
}
interface SourceLocation {
source: string;
start: Position;
end: Position;
}
interface Position {
line: number;
column: number;
}
interface Program extends Node {
body: Statement[];
blockParams: string[];
}
interface Statement extends Node {}
interface MustacheStatement extends Statement {
path: PathExpression | Literal;
params: Expression[];
hash: Hash;
escaped: boolean;
strip: StripFlags;
}
interface Decorator extends MustacheStatement { }
interface BlockStatement extends Statement {
path: PathExpression;
params: Expression[];
hash: Hash;
program: Program;
inverse: Program;
openStrip: StripFlags;
inverseStrip: StripFlags;
closeStrip: StripFlags;
}
interface DecoratorBlock extends BlockStatement { }
interface PartialStatement extends Statement {
name: PathExpression | SubExpression;
params: Expression[];
hash: Hash;
indent: string;
strip: StripFlags;
}
interface PartialBlockStatement extends Statement {
name: PathExpression | SubExpression;
params: Expression[],
hash: Hash,
program: Program,
openStrip: StripFlags,
closeStrip: StripFlags
}
interface ContentStatement extends Statement {
value: string;
original: StripFlags;
}
interface CommentStatement extends Statement {
value: string;
strip: StripFlags;
}
interface Expression extends Node {}
interface SubExpression extends Expression {
path: PathExpression;
params: Expression[];
hash: Hash;
}
interface PathExpression extends Expression {
data: boolean;
depth: number;
parts: string[];
original: string;
}
interface Literal extends Expression {}
interface StringLiteral extends Literal {
value: string;
original: string;
}
interface BooleanLiteral extends Literal {
value: boolean;
original: boolean;
}
interface NumberLiteral extends Literal {
value: number;
original: number;
}
interface UndefinedLiteral extends Literal {}
interface NullLiteral extends Literal {}
interface Hash extends Node {
pairs: HashPair[];
}
interface HashPair extends Node {
key: string;
value: Expression;
}
interface StripFlags {
open: boolean;
close: boolean;
}
interface helpers {
helperExpression(node: Node): boolean;
scopeId(path: PathExpression): boolean;
simpleId(path: PathExpression): boolean;
}
}
}
declare module "handlebars" {
export = Handlebars;
}

View File

@ -0,0 +1,8 @@
{
"resolution": "main",
"tree": {
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/90198235019d12c00b3ccca03a36cc3d1579d644/handlebars/index.d.ts",
"raw": "registry:dt/handlebars#4.0.5+20160810231743",
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/90198235019d12c00b3ccca03a36cc3d1579d644/handlebars/index.d.ts"
}
}

View File

@ -0,0 +1 @@
/// <reference path="globals/handlebars/index.d.ts" />

View File

@ -0,0 +1 @@
/// <reference path="@ms/odsp.d.ts" />