diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c5412fa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*] +tab_width = 4 +indent_size = 4 +trim_trailing_whitespace = true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f760286 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vs/ +.vscode/ +.cache/ +obj/ +node_modules/ +System Volume Information/ \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..affc1fa --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +.vs/ +.vscode/ +tools/ + +.editorconfig +.eslintignore +.eslintrc.json +.gitignore +.prettierrc.json +.babelrc.json \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..174ac3b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Kevin Hill + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs new file mode 100644 index 0000000..6cc827f --- /dev/null +++ b/Properties/Resources.Designer.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SSPM.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SSPM.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to (function(spGlobal) { + /// const notify = (message, title) => { + /// const textInfo = new StrokesPlus.Types.Internal.DisplayTextInfo(); + /// + /// textInfo.UsePrimaryScreen = true; + /// textInfo.Message = message; + /// textInfo.Title = title; + /// textInfo.TitleFont = new Font("Segoe UI", 18, host.flags(FontStyle.Bold)); + /// textInfo.TitleAlignment = "Right"; + /// textInfo.MessageFont = new Font("Segoe UI Semibold", 14); + /// textInfo.MessageAlignment = "Right"; + /// textInfo.Padding = 10; + /// textInfo. [rest of string was truncated]";. + /// + public static string sppm { + get { + return ResourceManager.GetString("sppm", resourceCulture); + } + } + } +} diff --git a/Properties/Resources.resx b/Properties/Resources.resx new file mode 100644 index 0000000..f94ec78 --- /dev/null +++ b/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\src\sppm.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6ef0062 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +## ScriptsPlus, a StrokesPlus.net Plugin + +### Enhance the scripting capabilities of S+ with a rich module library. +Inspired by the simplicity of jQuery, there are 40+ modules that extend and enhance the scripting capabilities within action scripts. +Many common `sp.xxxx` methods are wrapped to simplify their use and some wrapped together to create new tools. + +# Install +Download `ScriptsPlusPlugin.dll` from here and place it in `C:\Program Files\StrokesPlus.net\Plug-Ins` to be automatically picked up by S+ +You can also add it manually, or place it in your own plugins folder and add that path. + +# Loading + - Head to `Global Actions` + - Open the `Load/Unload` tab + - Check the box to enable the load script + - Paste in this snippet: `var $ = ScriptsPlus();` + - Profit! + +# Examples + +### Wrapped Methods +```javascript +// wraps `sp.MessageBox()` +$.alert("Hello World!"); + +// wraps `new DisplayTextInfo()` +$.toast("Hello World!"); + +// wraps `sp.sp.ShowBalloonTip()` +$.balloon("Hello World!"); +``` + +### Dialogs +```javascript +function getUserInput() { + var modal = $.dialog.create("Text Input Demo"); + + modal.show(input => $.alert(input, "Input")); +} + +getUserInput(); +``` + +### Popup Menus +```javascript +var { addToMenu, addToSubMenu, menuItem, show } = $.popup; + +var popup = $.popup.create(); +var addToMainMenu = $.popup.addToMenu(popup); + +var mastercam = menuItem("Mastercam"); +var addToDemo = $.popup.addToSubMenu(mastercam); + +addToDemo(menuItem("Hello World", `$.alert('Hello World')`)); +addToDemo(menuItem("Taco Bell", `$.alert('Taco Bell')`)); +addToDemo(menuItem("Is Good", `$.alert('Is Good')`)); + +addToMainMenu(mastercam); +addToMainMenu($.popup.spacer); +addToMainMenu($.popup.cancel); + +show(popup); +``` \ No newline at end of file diff --git a/bin/Release/sspm.dll b/bin/Release/sspm.dll new file mode 100644 index 0000000..29a59aa Binary files /dev/null and b/bin/Release/sspm.dll differ diff --git a/bin/Release/sspm.pdb b/bin/Release/sspm.pdb new file mode 100644 index 0000000..85e5652 Binary files /dev/null and b/bin/Release/sspm.pdb differ diff --git a/sppm.csproj b/sppm.csproj new file mode 100644 index 0000000..f6dc6a9 --- /dev/null +++ b/sppm.csproj @@ -0,0 +1,74 @@ + + + + + Debug + AnyCPU + {0000CF33-0000-0000-0000-000000000000} + Library + SSPM + sspm + v4.8 + 512 + true + true + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + prompt + 4 + false + + + + False + C:\Program Files\StrokesPlus.net\ClearScript.Core.dll + False + + + C:\Program Files\StrokesPlus.net\ClearScript.V8.dll + False + + + + + + + + + True + True + Resources.resx + + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + \ No newline at end of file diff --git a/sppm.sln b/sppm.sln new file mode 100644 index 0000000..d01b1a2 --- /dev/null +++ b/sppm.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sppm", "sppm.csproj", "{0000CF33-0000-0000-0000-000000000000}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0000CF33-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0000CF33-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0000CF33-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0000CF33-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EDD7BDD0-0D99-4905-B067-282AFA10DD39} + EndGlobalSection +EndGlobal diff --git a/src/sppm.cs b/src/sppm.cs new file mode 100644 index 0000000..d3c95c8 --- /dev/null +++ b/src/sppm.cs @@ -0,0 +1,22 @@ +using Microsoft.ClearScript; +using System.Windows.Forms; + +namespace SSPM +{ + public static class SSPM + { + public static string jsSource { get; } = Properties.Resources.sppm; + + public static void StrokesPlusInitStaticPlugin(ScriptEngine e) + { + try + { + e.Execute(jsSource); + } + catch (System.Exception err) + { + MessageBox.Show(err.Message, "SSPM Plugin Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/src/sppm.js b/src/sppm.js new file mode 100644 index 0000000..bb6b72d --- /dev/null +++ b/src/sppm.js @@ -0,0 +1,133 @@ +(function(spGlobal) { + const notify = (message, title) => { + const textInfo = new StrokesPlus.Types.Internal.DisplayTextInfo(); + + textInfo.UsePrimaryScreen = true; + textInfo.Message = message; + textInfo.Title = title; + textInfo.TitleFont = new Font("Segoe UI", 18, host.flags(FontStyle.Bold)); + textInfo.TitleAlignment = "Right"; + textInfo.MessageFont = new Font("Segoe UI Semibold", 14); + textInfo.MessageAlignment = "Right"; + textInfo.Padding = 10; + textInfo.Duration = 2000; + textInfo.Location = "bottomright"; + textInfo.Opacity = 0.9; + textInfo.ForeColor = "white"; + textInfo.BackColor = "SteelBlue"; + + return StrokesPlus.UI.TextOverlay.Show(textInfo); + } + + const alert = StrokesPlus.UI.Alert; + + const APPDATA = StrokesPlus.OS.Shell.ExpandEnvironmentVariables('%APPDATA%'); + const SP_APPDATA = System.IO.Path.Combine(APPDATA, 'StrokesPlus.net'); + const NODE_MODULES = System.IO.Path.Combine(SP_APPDATA, 'node_modules'); + const PKG_JSON = "package.json"; + + function npm(input) { + const NPM = 'C:\\Program Files\\nodejs\\npm.cmd'; + const CMD = `cd "${SP_APPDATA}" && "${NPM}" ${input}`; + + try { + StrokesPlus.OS.Shell.RunProgram('cmd.exe', '/C ' + CMD, '', 'hidden', true, true, true); + } catch (err) { + alert(err.toString(), "Error"); + } + } + + function resolve(id) { + const pkgPath = System.IO.Path.Combine(NODE_MODULES, id, PKG_JSON); + + if (System.IO.File.Exists(pkgPath)) { + return pkgPath; + } else { + alert(`${pkgPath} was not found`, "Error"); + } + } + + function readPackage(abspath) { + try { + return JSON.parse(System.IO.File.ReadAllText(abspath)); + } catch (error) { + alert(error, "error"); + } + } + + class Plugin { + static load(id) { + const pkgPath = resolve(id); + const plugin = new Plugin(pkgPath); + const src = plugin.source; + __spEngineWrapper.Engine.Evaluate(src); + } + static fromNpm(id) { + if (typeof id === "string") { + notify(id, `Installing from npm...`); + npm(`install --save ${id}`); + } else { + npm(`install`); + } + } + constructor(abspath) { + this.abspath = abspath; + this.resolvedPkg = this.abspath.replace("/", "\\").replace("\\\\", "\\"); + } + get pkgExists() { + return System.IO.File.Exists(this.resolvedPkg); + } + get pkg() { + const contents = System.IO.File.ReadAllText(this.resolvedPkg); + try { + return JSON.parse(contents); + } catch (error) { + return {}; + } + } + get mainEntry() { + const path = this.resolvedPkg.replace(PKG_JSON, ""); + return System.IO.Path.Combine(path, this.pkg.main); + } + get source() { + try { + return System.IO.File.ReadAllText(this.mainEntry); + } catch (error) { + return alert(abspath, 'File Read Error'); + } + } + } + + const SSPM = class { + constructor() { + // + } + + install(id) { + if (typeof id === "string") { + notify(`Installing "${id}" from npmjs`, "StrokesPlus Package Manager"); + npm(`install --save ${id}`); + } else { + npm(`install`); + } + } + } + + function once(fn) { + if (__spEngineWrapper.Engine.Name == StrokesPlus.ScriptEngine.List.Last().Engine.Name) { + fn(); + } + } + + spGlobal["SPPM"] = SPPM; + spGlobal["Plugin"] = Plugin; + spGlobal["sppm"] = new spGlobal["SPPM"](); +})(this); +// +//////////////////////////////////////////////////////////////////// +// +//sppm.install('@spcsp/explore-settings-json'); +//Plugin.load('@spcsp/explore-settings-json'); + +//Plugin.load('@spcsp/osd-toast'); +//toast("hi");