diff --git a/.gitignore b/.gitignore index f760286..7bc3999 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ .cache/ obj/ node_modules/ -System Volume Information/ \ No newline at end of file +System Volume Information/ + +# ignore everything except the plugin +bin/Release/* +!bin/Release/sppm.dll +!bin/Release/sppm.pdb \ No newline at end of file diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs index 6cc827f..89a6c66 100644 --- a/Properties/Resources.Designer.cs +++ b/Properties/Resources.Designer.cs @@ -8,10 +8,10 @@ // //------------------------------------------------------------------------------ -namespace SSPM.Properties { +namespace SPPM.Properties { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,15 +23,15 @@ namespace SSPM.Properties { [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. /// @@ -39,13 +39,13 @@ internal Resources() { 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); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SPPM.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. @@ -59,20 +59,20 @@ internal Resources() { 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; + /// 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 { diff --git a/bin/Debug/sppm.dll b/bin/Debug/sppm.dll new file mode 100644 index 0000000..d58d8ac Binary files /dev/null and b/bin/Debug/sppm.dll differ diff --git a/bin/Debug/sppm.pdb b/bin/Debug/sppm.pdb new file mode 100644 index 0000000..4300788 Binary files /dev/null and b/bin/Debug/sppm.pdb differ diff --git a/bin/Release/sppm.dll b/bin/Release/sppm.dll new file mode 100644 index 0000000..410b9ab Binary files /dev/null and b/bin/Release/sppm.dll differ diff --git a/bin/Release/sppm.pdb b/bin/Release/sppm.pdb new file mode 100644 index 0000000..ce95381 Binary files /dev/null and b/bin/Release/sppm.pdb differ diff --git a/bin/Release/sspm.dll b/bin/Release/sspm.dll deleted file mode 100644 index 29a59aa..0000000 Binary files a/bin/Release/sspm.dll and /dev/null differ diff --git a/bin/Release/sspm.pdb b/bin/Release/sspm.pdb deleted file mode 100644 index 85e5652..0000000 Binary files a/bin/Release/sspm.pdb and /dev/null differ diff --git a/sppm.csproj b/sppm.csproj index f6dc6a9..ae6b6a7 100644 --- a/sppm.csproj +++ b/sppm.csproj @@ -6,8 +6,8 @@ AnyCPU {0000CF33-0000-0000-0000-000000000000} Library - SSPM - sspm + SPPM + sppm v4.8 512 true @@ -33,7 +33,7 @@ false - + False C:\Program Files\StrokesPlus.net\ClearScript.Core.dll False @@ -42,9 +42,19 @@ C:\Program Files\StrokesPlus.net\ClearScript.V8.dll False + + False + ..\..\..\..\..\..\Program Files\StrokesPlus.net\Newtonsoft.Json.dll + False + + + ..\..\..\..\..\..\Program Files\StrokesPlus.net\StrokesPlus.net.exe + False + False + - + @@ -53,6 +63,7 @@ True Resources.resx + diff --git a/sppm.sln b/sppm.sln index d01b1a2..71b8db2 100644 --- a/sppm.sln +++ b/sppm.sln @@ -5,6 +5,10 @@ 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 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sppm-tests", "..\sppm-tests\sppm-tests.csproj", "{E0702065-4972-46BE-9C7F-826C47D1FABE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sppm-demo", "..\sppm-demo\sppm-demo.csproj", "{FDCF12E0-B5BF-4A49-8DBC-951D903F0379}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +19,14 @@ Global {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 + {E0702065-4972-46BE-9C7F-826C47D1FABE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0702065-4972-46BE-9C7F-826C47D1FABE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0702065-4972-46BE-9C7F-826C47D1FABE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0702065-4972-46BE-9C7F-826C47D1FABE}.Release|Any CPU.Build.0 = Release|Any CPU + {FDCF12E0-B5BF-4A49-8DBC-951D903F0379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDCF12E0-B5BF-4A49-8DBC-951D903F0379}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDCF12E0-B5BF-4A49-8DBC-951D903F0379}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDCF12E0-B5BF-4A49-8DBC-951D903F0379}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/package.cs b/src/package.cs new file mode 100644 index 0000000..2df4aab --- /dev/null +++ b/src/package.cs @@ -0,0 +1,89 @@ +using System.CodeDom.Compiler; +using System.Collections.Generic; +using Newtonsoft.Json; +using static Newtonsoft.Json.Required; +using static Newtonsoft.Json.NullValueHandling; + +namespace PackageJson +{ + [GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class Author + { + [JsonProperty("name", Required = DisallowNull, NullValueHandling = Ignore)] + public string Name { get; set; } + + [JsonProperty("email", Required = DisallowNull, NullValueHandling = Ignore)] + public string Email { get; set; } + + [JsonProperty("url", Required = DisallowNull, NullValueHandling = Ignore)] + public string Url { get; set; } + + private IDictionary _additionalProperties = new Dictionary(); + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties; } + set { _additionalProperties = value; } + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class PublishConfig + { + [JsonProperty("access", Required = DisallowNull, NullValueHandling = Ignore)] + public string Access { get; set; } + + private IDictionary _additionalProperties = new Dictionary(); + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties; } + set { _additionalProperties = value; } + } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v13.0.0.0)")] + public partial class Root + { + [JsonProperty("name", Required = DisallowNull, NullValueHandling = Ignore)] + public string Name { get; set; } + + [JsonProperty("version", Required = DisallowNull, NullValueHandling = Ignore)] + public string Version { get; set; } + + [JsonProperty("private", Required = DisallowNull, NullValueHandling = Ignore)] + public bool Private { get; set; } + + [JsonProperty("description", Required = DisallowNull, NullValueHandling = Ignore)] + public string Description { get; set; } + + [JsonProperty("keywords", Required = DisallowNull, NullValueHandling = Ignore)] + public ICollection Keywords { get; set; } + + [JsonProperty("license", Required = DisallowNull, NullValueHandling = Ignore)] + public string License { get; set; } + + [JsonProperty("author", Required = DisallowNull, NullValueHandling = Ignore)] + public Author Author { get; set; } + + [JsonProperty("repository", Required = DisallowNull, NullValueHandling = Ignore)] + public Author Repository { get; set; } + + [JsonProperty("main", Required = DisallowNull, NullValueHandling = Ignore)] + public string Main { get; set; } + + [JsonProperty("publishConfig", Required = DisallowNull, NullValueHandling = Ignore)] + public PublishConfig PublishConfig { get; set; } + + private IDictionary _additionalProperties = new Dictionary(); + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties; } + set { _additionalProperties = value; } + } + } +} diff --git a/src/sppm.cs b/src/sppm.cs index d3c95c8..27abd52 100644 --- a/src/sppm.cs +++ b/src/sppm.cs @@ -1,22 +1,138 @@ -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); - } - } - } -} +using System; +using System.IO; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using Microsoft.ClearScript; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using static StrokesPlus.net.Engine.StrokesPlusClasses.Types.Internal; +using static StrokesPlus.net.Engine.StrokesPlusClasses.UI; + +namespace SPPM +{ + public static class NPM + { + public static void Exec(string input) => Run(input, true); + public static void ExecAsync(string input) => Run(input, false); + private static int Run(string input, bool waitForExit) + { + Environment.CurrentDirectory = Paths.SP_APPDATA; + + var info = new ProcessStartInfo("C:\\Program Files\\nodejs\\npm.cmd") + { + Arguments = input, + CreateNoWindow = true, + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden, + }; + + var exitCode = 0; + + if (waitForExit) + { + using (var proc = Process.Start(info)) + { + proc.WaitForExit(); + exitCode = proc.ExitCode; + } + } + else + { + Process.Start(info); + return 0; + } + + return exitCode; + } + } + public static class SPPM + { + public static string JS_SOURCE { get; } = Properties.Resources.sppm; + public static string PACKAGE_JSON { get; } = "package.json"; + public static ScriptEngine Engine { get; set; } + public static void StrokesPlusInitStaticPlugin(ScriptEngine engine) => Engine = engine; + public static void Install(string pkgId) + { + // + } + public static void LoadClearScriptModule() + { + try { + Engine.Execute(JS_SOURCE); + } catch (Exception err) { + ShowError(err.Message); + } + } + public static string Resolve(string pkgId) + { + string pkgPath = Path.Combine(Paths.NODE_MODULES, pkgId, PACKAGE_JSON); + + return Path.GetFullPath(pkgPath); + } + public static bool Exists(string pkgId) + { + return File.Exists(ResolvePackage(pkgId)); + } + public static void Load(string pkgId) { + if (Exists(pkgId)) { + Engine.Evaluate(ResolveMain(pkgId)); + } else { + ShowError($"{pkgId} was not found."); + } + } + public static void Load(string[] pkgIds) + { + Array.ForEach(pkgIds, Load); + } + + public static string ResolveMain(string pkgId) + { + JObject packgage = ReadPackage(pkgId); + string mainEntry = packgage.GetValue("main").ToString(); + + return Path.GetFullPath(Path.Combine(Resolve(pkgId), mainEntry)); + } + public static string ResolvePackage(string pkgId) + { + return Path.Combine(Resolve(pkgId), PACKAGE_JSON); + } + public static JObject ReadPackage(string pkgId) + { + using (StreamReader reader = File.OpenText(ResolvePackage(pkgId))) + { + return (JObject) JToken.ReadFrom(new JsonTextReader(reader)); + } + } + public static void Notify(string message, string title) + { + DisplayTextInfo textInfo = new DisplayTextInfo(); + + textInfo.UsePrimaryScreen = true; + textInfo.Message = message; + textInfo.Title = title; + textInfo.TitleFont = new Font("Segoe UI", 18, FontStyle.Bold); + textInfo.TitleAlignment = "Right"; + textInfo.MessageFont = new Font("Segoe UI Semibold", 14); + textInfo.MessageAlignment = "Right"; + textInfo.Padding = 10; + textInfo.Duration = 2000; + textInfo.Location = "topright"; + textInfo.Opacity = 1; + textInfo.ForeColor = "SteelBlue"; + textInfo.BackColor = "White"; + + TextOverlay.Show(textInfo); + } + public static void ShowError(object what) + { + MessageBox.Show(what.ToString(), "SPPM | Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + public static class Paths + { + public static string APPDATA { get; } = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + public static string SP_APPDATA { get; } = Path.Combine(APPDATA, "StrokesPlus.net"); + public static string NODE_MODULES { get; } = Path.Combine(SP_APPDATA, "node_modules"); + } +} diff --git a/src/sppm.js b/src/sppm.js index bb6b72d..1af749d 100644 --- a/src/sppm.js +++ b/src/sppm.js @@ -1,133 +1,63 @@ -(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) { +var sppm = (() => { + 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"; + + const sppm = { + readPackage(abspath) { + try { + return JSON.parse(System.IO.File.ReadAllText(abspath)); + } catch (error) { + sppm.notify(error, "error"); + } + }, + install(id, opts) { if (typeof id === "string") { - notify(`Installing "${id}" from npmjs`, "StrokesPlus Package Manager"); - npm(`install --save ${id}`); + sppm.notify(`Installing "${id}" from npmjs`, "StrokesPlus Package Manager"); + sppm.npm(`install --save ${id}`, opts); } else { - npm(`install`); + sppm.npm(`install`, opts); } } - } - - function once(fn) { - if (__spEngineWrapper.Engine.Name == StrokesPlus.ScriptEngine.List.Last().Engine.Name) { - fn(); + }; + + class Plugin { + static load(id) { + const pkgPath = SPPM.resolve(id); + const plugin = new Plugin(pkgPath); + const src = plugin.source; + __spEngineWrapper.Engine.Evaluate(src); + } + 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 sppm.notify(abspath, 'File Read Error'); + } } } - - 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"); + sppm.Plugin = Plugin; + + return sppm; +})(); \ No newline at end of file