2019-03-12 23:24:46 +00:00
import JSFiddle = require ( "jsfiddle" ) ;
2019-03-19 22:17:35 +01:00
import { QuickDiffProvider , Uri , CancellationToken , ProviderResult , WorkspaceFolder , workspace , window , env } from "vscode" ;
2019-03-12 23:24:46 +00:00
import * as path from 'path' ;
2019-03-19 03:06:13 +01:00
/** Represents one JSFiddle data and meta-data. */
2019-03-12 23:24:46 +00:00
export class Fiddle {
2019-03-19 03:06:13 +01:00
constructor ( public slug : string , public version : number , public data : FiddleData ) { }
2019-03-12 23:24:46 +00:00
}
2019-03-19 03:06:13 +01:00
/** Represents JSFiddle HTML, JavaScript and CSS text. */
2019-03-12 23:24:46 +00:00
export interface FiddleData {
html : string ;
js : string ;
css : string ;
}
export function areIdentical ( first : FiddleData , second : FiddleData ) : boolean {
2019-05-10 14:45:55 -07:00
return first . html === second . html
&& first . css === second . css
&& first . js === second . js ;
2019-03-12 23:24:46 +00:00
}
export const JSFIDDLE_SCHEME = 'jsfiddle' ;
export class FiddleRepository implements QuickDiffProvider {
2019-03-19 03:06:13 +01:00
constructor ( private workspaceFolder : WorkspaceFolder , private fiddleSlug : string ) { }
2019-03-12 23:24:46 +00:00
provideOriginalResource ? ( uri : Uri , token : CancellationToken ) : ProviderResult < Uri > {
// converts the local file uri to jsfiddle:file.ext
let relativePath = workspace . asRelativePath ( uri . fsPath ) ;
return Uri . parse ( ` ${ JSFIDDLE_SCHEME } : ${ relativePath } ` ) ;
}
2019-03-19 03:06:13 +01:00
/ * *
* Enumerates the resources under source control .
* /
provideSourceControlledResources ( ) : Uri [ ] {
return [
Uri . file ( this . createLocalResourcePath ( 'html' ) ) ,
Uri . file ( this . createLocalResourcePath ( 'js' ) ) ,
2019-03-19 22:17:35 +01:00
Uri . file ( this . createLocalResourcePath ( 'css' ) ) ] ;
2019-03-19 03:06:13 +01:00
}
/ * *
* Creates a local file path in the local workspace that corresponds to the part of the
* fiddle denoted by the given extension .
*
* @param extension fiddle part , which is also used as a file extension
* @returns path of the locally cloned fiddle resource ending with the given extension
* /
createLocalResourcePath ( extension : string ) {
return path . join ( this . workspaceFolder . uri . fsPath , this . fiddleSlug + '.' + extension ) ;
}
2019-03-12 23:24:46 +00:00
}
2019-03-19 03:06:13 +01:00
const DEMO : FiddleData [ ] = [
{
html : '<div class="hi">Hi</div>' ,
css : ` .hi { \ n color: red; \ n} ` ,
js : '$(".hi").fadeOut();'
}
] ;
// emulates prior versions mock-committed in previous sessions
2019-05-10 14:34:54 -07:00
var demoVersionOffset : number | undefined = undefined ;
2019-03-19 03:06:13 +01:00
export async function downloadFiddle ( slug : string , version : number | undefined ) : Promise < Fiddle > {
2019-03-12 23:24:46 +00:00
2019-03-19 03:06:13 +01:00
if ( slug === "demo" ) {
// use mock fiddle
2019-05-10 14:45:55 -07:00
if ( demoVersionOffset === undefined && version === undefined ) { version = 0 ; }
if ( demoVersionOffset === undefined ) { demoVersionOffset = version ; }
2019-03-20 10:31:44 +01:00
let maxDemoVersion = DEMO . length - 1 + demoVersionOffset ;
2019-05-10 14:45:55 -07:00
if ( version === undefined ) { version = maxDemoVersion ; }
2019-03-12 23:24:46 +00:00
2019-03-19 22:17:35 +01:00
if ( version >= 0 && version <= maxDemoVersion ) {
2019-03-19 03:06:13 +01:00
// mock all versions committed in previous sessions by the first version
2019-03-19 22:17:35 +01:00
let index = Math . max ( 0 , version - demoVersionOffset ) ;
2019-03-19 03:06:13 +01:00
let fiddleData = DEMO [ index ] ;
return new Fiddle ( slug , version , fiddleData ) ;
2019-03-12 23:24:46 +00:00
}
else {
2019-05-10 14:45:55 -07:00
throw new Error ( "Invalid demo fiddle version." ) ;
2019-03-12 23:24:46 +00:00
}
}
2019-03-19 03:06:13 +01:00
let id = toFiddleId ( slug , version ) ;
2019-03-12 23:24:46 +00:00
return new Promise < Fiddle > ( ( resolve , reject ) = > {
JSFiddle . getFiddle ( id , ( err : any , fiddleData : any ) = > {
// handle error
2019-05-10 14:45:55 -07:00
if ( err ) { reject ( err ) ; }
2019-03-12 23:24:46 +00:00
2019-03-19 03:06:13 +01:00
let fiddle = new Fiddle ( slug , version , fiddleData ) ;
2019-03-12 23:24:46 +00:00
resolve ( fiddle ) ;
} ) ;
} ) ;
}
2019-05-10 14:34:54 -07:00
export async function uploadFiddle ( slug : string , version : number , html : string , js : string , css : string ) : Promise < Fiddle | undefined > {
2019-03-12 23:24:46 +00:00
2019-03-19 03:06:13 +01:00
if ( slug === "demo" ) {
// using mock fiddle
let fiddleData : FiddleData = { html : html , js : js , css : css } ;
DEMO . push ( fiddleData ) ;
return new Fiddle ( slug , version , fiddleData ) ;
2019-03-12 23:24:46 +00:00
}
2019-03-19 22:17:35 +01:00
else {
2019-03-12 23:24:46 +00:00
2019-03-19 22:17:35 +01:00
let answer = await window . showQuickPick ( [ "Yes, open in the browser. I will paste the new Fiddle code, discard changes, refresh source control and checkout latest." , "No, I was just clicking around." ] ,
{ placeHolder : "JS Fiddle saving is not supported. Do you want to open the JSFiddle in the browser?" } ) ;
2019-03-12 23:24:46 +00:00
2019-03-19 22:17:35 +01:00
if ( answer && answer . toLowerCase ( ) . startsWith ( "yes" ) ) {
env . openExternal ( Uri . parse ( ` https://jsfiddle.net/ ${ slug } / ` ) ) ;
return undefined ;
}
2019-03-12 23:24:46 +00:00
2019-03-19 22:17:35 +01:00
if ( false ) {
// this, sadly, does not work as advertised
let data = {
slug : slug ,
version : version ,
html : html ,
js : js ,
css : css
} ;
return new Promise < Fiddle > ( ( resolve , reject ) = > {
JSFiddle . saveFiddle ( data , ( err : any , fiddleData : any ) = > {
// handle error
if ( err ) {
reject ( err ) ;
}
else {
let fiddle = new Fiddle ( slug , version , fiddleData ) ;
resolve ( fiddle ) ;
}
} ) ;
} ) ;
}
else {
return undefined ;
}
}
2019-03-12 23:24:46 +00:00
}
2019-05-17 00:52:52 +02:00
export function toFiddleId ( slug : string , version : number | undefined ) : string {
2019-03-12 23:24:46 +00:00
if ( version === undefined ) {
2019-03-19 03:06:13 +01:00
return slug ;
2019-03-12 23:24:46 +00:00
}
else {
2019-03-19 03:06:13 +01:00
return slug + '/' + version ;
2019-03-12 23:24:46 +00:00
}
}
/ * *
* Gets extension trimming the dot character .
* @param uri document uri
* /
export function toExtension ( uri : Uri ) : string {
return path . extname ( uri . fsPath ) . substr ( 1 ) ;
}