From 306cbb0f83504c44182c6e390cdc7e21f6f7d7c8 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Sun, 19 Sep 2021 09:56:24 -0400 Subject: [PATCH] Create project scaffolding. --- .github/ISSUE_TEMPLATE/bug_report.md | 27 ++++ .github/ISSUE_TEMPLATE/feature_request.md | 8 ++ .github/ISSUE_TEMPLATE/other.md | 8 ++ .github/workflows/ci.yml | 146 ++++++++++++++++++++++ .gitignore | 4 + Cargo.toml | 35 ++++++ LICENSE | 21 ++++ README.md | 3 + deployment/npm/.npmignore | 2 + deployment/npm/README.md | 16 +++ deployment/npm/index.d.ts | 2 + deployment/npm/index.js | 34 +++++ deployment/npm/index.test.js | 9 ++ deployment/npm/package-lock.json | 14 +++ deployment/npm/package.json | 29 +++++ deployment/npm/setup.js | 21 ++++ deployment/schema.json | 59 +++++++++ dprint.json | 20 +++ src/configuration/builder.rs | 127 +++++++++++++++++++ src/configuration/configuration.rs | 11 ++ src/configuration/mod.rs | 7 ++ src/configuration/resolve_config.rs | 58 +++++++++ src/format_text.rs | 9 ++ src/lib.rs | 15 +++ src/wasm_plugin.rs | 58 +++++++++ 25 files changed, 743 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/other.md create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 deployment/npm/.npmignore create mode 100644 deployment/npm/README.md create mode 100644 deployment/npm/index.d.ts create mode 100644 deployment/npm/index.js create mode 100644 deployment/npm/index.test.js create mode 100644 deployment/npm/package-lock.json create mode 100644 deployment/npm/package.json create mode 100644 deployment/npm/setup.js create mode 100644 deployment/schema.json create mode 100644 dprint.json create mode 100644 src/configuration/builder.rs create mode 100644 src/configuration/configuration.rs create mode 100644 src/configuration/mod.rs create mode 100644 src/configuration/resolve_config.rs create mode 100644 src/format_text.rs create mode 100644 src/lib.rs create mode 100644 src/wasm_plugin.rs diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..1028a5a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** + +dprint-plugin-dockerfile version: x.x.x + +**Input Code** + +```dockerfile +``` + +**Expected Output** + +```dockerfile +``` + +**Actual Output** + +```dockerfile +``` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..e7cd4ca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,8 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/ISSUE_TEMPLATE/other.md b/.github/ISSUE_TEMPLATE/other.md new file mode 100644 index 0000000..136c638 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.md @@ -0,0 +1,8 @@ +--- +name: Other +about: Something that doesn't fall in the other categories +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8f2e6d7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,146 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.config.kind }} ${{ matrix.config.os }} + runs-on: ${{ matrix.config.os }} + strategy: + matrix: + config: + - os: ubuntu-latest + kind: test_release + - os: ubuntu-latest + kind: test_debug + + env: + CARGO_INCREMENTAL: 0 + RUST_BACKTRACE: full + + steps: + - uses: actions/checkout@v2 + - name: Install wasm32 target + if: matrix.config.kind == 'test_release' + run: rustup target add wasm32-unknown-unknown + + - uses: Swatinem/rust-cache@v1 + + - name: Build debug + if: matrix.config.kind == 'test_debug' + run: cargo build --verbose + - name: Build release + if: matrix.config.kind == 'test_release' + run: cargo build --target wasm32-unknown-unknown --features wasm --release --verbose + + - name: Test debug + if: matrix.config.kind == 'test_debug' + run: cargo test --verbose + - name: Test release + if: matrix.config.kind == 'test_release' + run: cargo test --release --verbose + + - name: Get tag version + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + id: get_tag_version + run: echo ::set-output name=TAG_VERSION::${GITHUB_REF/refs\/tags\//} + + # NPM + - uses: actions/setup-node@v2 + if: matrix.config.kind == 'test_release' + with: + node-version: '14.x' + registry-url: 'https://registry.npmjs.org' + + - name: Setup and test npm deployment + if: matrix.config.kind == 'test_release' + run: | + cd deployment/npm + npm install + node setup.js ${{ steps.get_tag_version.outputs.TAG_VERSION }} + npm run test + + - name: npm publish + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + cd deployment/npm + npm publish --access public + git reset --hard + + # CARGO PUBLISH + - name: Cargo login + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + run: cargo login ${{ secrets.CRATES_TOKEN }} + + - name: Cargo publish + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + run: cargo publish + + # GITHUB RELEASE + - name: Pre-release + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + run: | + # update config schema to have version + sed -i 's/dockerfile-0.0.0.json/dockerfile-${{ steps.get_tag_version.outputs.TAG_VERSION }}.json/' deployment/schema.json + # rename the wasm file + (cd target/wasm32-unknown-unknown/release/ && mv dprint_plugin_dockerfile.wasm dockerfile.wasm) + - name: Release + uses: softprops/action-gh-release@v1 + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + files: | + target/wasm32-unknown-unknown/release/dockerfile.wasm + deployment/schema.json + body: | + ## Install + + [Install](https://dprint.dev/install/) and [setup](https://dprint.dev/setup/) dprint. + + Then in your project's dprint configuration file: + + 1. Specify the plugin url in the `"plugins"` array. + 2. Ensure `.dockerfile` file extensions are matched in an `"includes"` pattern. + 3. Add a `"dockerfile"` configuration property if desired. + ```jsonc + { + // ...etc... + "dockerfile": { + // config goes here + }, + "includes": [ + "**/*.{dockerfile}" + ], + "plugins": [ + "https://plugins.dprint.dev/dockerfile-${{ steps.get_tag_version.outputs.TAG_VERSION }}.wasm" + ] + } + ``` + + ## JS Formatting API + + * [JS Formatter](https://github.com/dprint/js-formatter) - Browser/Deno and Node + * [npm package](https://www.npmjs.com/package/@dprint/dockerfile) + draft: false + + # PLUGIN PUBLISH + - name: Checkout plugins repo + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + uses: actions/checkout@v2 + with: + repository: dprint/plugins + token: ${{ secrets.CI_REPO_PAT }} # github.token is scoped to current repo, so use this to push to other repo + path: dprint-plugins + - name: Plugin publish + if: matrix.config.kind == 'test_release' && startsWith(github.ref, 'refs/tags/') + run: | + cd dprint-plugins + node scripts/replace-plugin.js dprint-plugin-dockerfile ${{ steps.get_tag_version.outputs.TAG_VERSION }} dockerfile-${{ steps.get_tag_version.outputs.TAG_VERSION }} + git add . + git config user.name "David Sherret" + git config user.email "dsherret@users.noreply.github.com" + git commit -m "dprint-plugin-dockerfile ${{ steps.get_tag_version.outputs.TAG_VERSION }}" + git push origin main diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe96a74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +Cargo.lock +deployment/npm/buffer.generated.js +deployment/npm/node_modules diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c183f47 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "dprint-plugin-dockerfile" +version = "0.0.1" +authors = ["David Sherret "] +edition = "2018" +homepage = "https://github.com/dprint/dprint-plugin-dockerfile" +keywords = ["formatting", "formatter", "docker", "dockerfile"] +license = "MIT" +repository = "https://github.com/dprint/dprint-plugin-dockerfile" +description = "A WIP dockerfile formatter for dprint." + +[lib] +crate-type = ["lib", "cdylib"] + +[profile.release] +opt-level = 3 +debug = false +lto = true +debug-assertions = false +overflow-checks = false +panic = "abort" + +[features] +wasm = ["serde_json", "dprint-core/wasm"] +tracing = ["dprint-core/tracing"] + +[dependencies] +dockerfile-parser = "0.7.1" +dprint-core = { version = "0.44.0", features = ["formatting"] } +serde = { version = "1.0.88", features = ["derive"] } +serde_json = { version = "1.0", optional = true } + +[dev-dependencies] +dprint-development = "0.4.1" +serde_json = { version = "1.0" } diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4d08264 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 David Sherret + +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/README.md b/README.md new file mode 100644 index 0000000..6c958e6 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# dprint-plugin-dockerfile + +WIP - Future home of a dockerfile formatter. diff --git a/deployment/npm/.npmignore b/deployment/npm/.npmignore new file mode 100644 index 0000000..4d36f60 --- /dev/null +++ b/deployment/npm/.npmignore @@ -0,0 +1,2 @@ +setup.js +index.test.js diff --git a/deployment/npm/README.md b/deployment/npm/README.md new file mode 100644 index 0000000..9315879 --- /dev/null +++ b/deployment/npm/README.md @@ -0,0 +1,16 @@ +# @dprint/dockerfile + +npm distribution of [dprint-plugin-dockerfile](https://github.com/dprint/dprint-plugin-dockerfile). + +Use this with [@dprint/formatter](https://github.com/dprint/js-formatter) or just use @dprint/formatter and download the [dprint-plugin-dockerfile WASM file](https://github.com/dprint/dprint-plugin-dockerfile/releases). + +## Example + +```ts +import { getBuffer } from "@dprint/dockerfile"; +import { createFromBuffer } from "@dprint/formatter"; + +const formatter = createFromBuffer(getBuffer()); + +console.log(formatter.formatText("test.toml", "RUN /bin/bash")); +``` diff --git a/deployment/npm/index.d.ts b/deployment/npm/index.d.ts new file mode 100644 index 0000000..ac2dfea --- /dev/null +++ b/deployment/npm/index.d.ts @@ -0,0 +1,2 @@ +/** Gets a buffer representing the WASM module. */ +export function getBuffer(): ArrayBuffer; diff --git a/deployment/npm/index.js b/deployment/npm/index.js new file mode 100644 index 0000000..8f35196 --- /dev/null +++ b/deployment/npm/index.js @@ -0,0 +1,34 @@ +/** + * Gets a buffer representing the WASM module. + * @returns {ArrayBuffer} + */ +function getBuffer() { + const encodedBuffer = require("./buffer.generated").encodedBuffer; + return decodeEncodedBuffer(encodedBuffer); +} + +/** + * @param {string} encodedBuffer + * @returns {ArrayBuffer} + */ +function decodeEncodedBuffer(encodedBuffer) { + // https://stackoverflow.com/a/51473757/188246 + const binaryString = toBinaryString(); + const bytes = new Uint8Array(binaryString.length); + for (let i = 0; i < binaryString.length; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes.buffer; + + function toBinaryString() { + if (typeof atob === "function") { + return atob(encodedBuffer); + } else { + return Buffer.from(encodedBuffer, "base64").toString("binary"); + } + } +} + +module.exports = { + getBuffer, +}; diff --git a/deployment/npm/index.test.js b/deployment/npm/index.test.js new file mode 100644 index 0000000..9b5bb55 --- /dev/null +++ b/deployment/npm/index.test.js @@ -0,0 +1,9 @@ +// @ts-check +const assert = require("assert"); +const createFromBuffer = require("@dprint/formatter").createFromBuffer; +const getBuffer = require("./index").getBuffer; + +const formatter = createFromBuffer(getBuffer()); +const result = formatter.formatText("file.dockerfile", "RUN /bin/bash"); + +assert.strictEqual(result, "RUN /bin/bash\n"); diff --git a/deployment/npm/package-lock.json b/deployment/npm/package-lock.json new file mode 100644 index 0000000..21a9913 --- /dev/null +++ b/deployment/npm/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "@dprint/dockerfile", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@dprint/formatter": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@dprint/formatter/-/formatter-0.1.4.tgz", + "integrity": "sha512-L7PifpVn+u1fH+5jUNv6W2Ie5LYvG5rlXCB9hn/byozAj1WOjaZczwvWmYWNS2zObF3d+PjKf6ON+HCPHjqNvQ==", + "dev": true + } + } +} diff --git a/deployment/npm/package.json b/deployment/npm/package.json new file mode 100644 index 0000000..0bfb594 --- /dev/null +++ b/deployment/npm/package.json @@ -0,0 +1,29 @@ +{ + "name": "@dprint/dockerfile", + "version": "0.0.0", + "description": "Wasm buffer for dprint-plugin-dockerfile.", + "main": "./index.js", + "types": "./index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/dprint/dprint-plugin-dockerfile.git" + }, + "keywords": [ + "dockerfile", + "code", + "formatter", + "dprint" + ], + "author": "David Sherret", + "license": "MIT", + "bugs": { + "url": "https://github.com/dprint/dprint-plugin-dockerfile/issues" + }, + "homepage": "https://github.com/dprint/dprint-plugin-dockerfile#readme", + "scripts": { + "test": "node index.test.js" + }, + "devDependencies": { + "@dprint/formatter": "~0.1.4" + } +} diff --git a/deployment/npm/setup.js b/deployment/npm/setup.js new file mode 100644 index 0000000..074a475 --- /dev/null +++ b/deployment/npm/setup.js @@ -0,0 +1,21 @@ +// @ts-check +const fs = require("fs"); +const path = require("path"); +const args = process.argv.slice(2); +const wasmPath = path.join(__dirname, "../../target/wasm32-unknown-unknown/release/dprint_plugin_dockerfile.wasm"); +const wasmBytes = fs.readFileSync(wasmPath); + +let output = "module.exports.encodedBuffer = \""; +output += wasmBytes.toString("base64"); +output += "\";\n"; + +fs.writeFileSync(path.join(__dirname, "buffer.generated.js"), output); + +if (args.length > 0) { + // update the version based on the first argument + const packageJsonPath = path.join(__dirname, "package.json"); + const packageJsonText = fs.readFileSync(packageJsonPath, "utf8"); + const packageJson = JSON.parse(packageJsonText); + packageJson.version = args[0]; + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, undefined, 2) + "\n"); +} diff --git a/deployment/schema.json b/deployment/schema.json new file mode 100644 index 0000000..b47c961 --- /dev/null +++ b/deployment/schema.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://plugins.dprint.dev/schemas/dockerfile-0.0.0.json", + "type": "object", + "definitions": { + "useTabs": { + "description": "Whether to use tabs (true) or spaces (false).", + "type": "boolean", + "default": false, + "oneOf": [{ + "const": true, + "description": "" + }, { + "const": false, + "description": "" + }] + }, + "newLineKind": { + "description": "The kind of newline to use.", + "type": "string", + "default": "lf", + "oneOf": [{ + "const": "auto", + "description": "For each file, uses the newline kind found at the end of the last line." + }, { + "const": "crlf", + "description": "Uses carriage return, line feed." + }, { + "const": "lf", + "description": "Uses line feed." + }, { + "const": "system", + "description": "Uses the system standard (ex. crlf on Windows)." + }] + } + }, + "properties": { + "locked": { + "description": "Whether the configuration is not allowed to be overriden or extended.", + "type": "boolean" + }, + "lineWidth": { + "description": "The width of a line the printer will try to stay under. Note that the printer may exceed this width in certain cases.", + "default": 120, + "type": "number" + }, + "indentWidth": { + "description": "The number of characters for an indent.", + "default": 2, + "type": "number" + }, + "useTabs": { + "$ref": "#/definitions/useTabs" + }, + "newLineKind": { + "$ref": "#/definitions/newLineKind" + } + } +} diff --git a/dprint.json b/dprint.json new file mode 100644 index 0000000..c4dba1d --- /dev/null +++ b/dprint.json @@ -0,0 +1,20 @@ +{ + "incremental": true, + "indentWidth": 2, + "rustfmt": { + "lineWidth": 160 + }, + "includes": ["**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,toml,rs}"], + "excludes": [ + "**/node_modules", + "**/*-lock.json", + "**/target" + ], + "plugins": [ + "https://plugins.dprint.dev/typescript-0.55.0.wasm", + "https://plugins.dprint.dev/json-0.13.0.wasm", + "https://plugins.dprint.dev/markdown-0.10.0.wasm", + "https://plugins.dprint.dev/toml-0.5.1.wasm", + "https://plugins.dprint.dev/rustfmt-0.4.0.exe-plugin@c6bb223ef6e5e87580177f6461a0ab0554ac9ea6b54f78ea7ae8bf63b14f5bc2" + ] +} diff --git a/src/configuration/builder.rs b/src/configuration/builder.rs new file mode 100644 index 0000000..53dab9a --- /dev/null +++ b/src/configuration/builder.rs @@ -0,0 +1,127 @@ +use dprint_core::configuration::{resolve_global_config, ConfigKeyMap, ConfigKeyValue, GlobalConfiguration, NewLineKind}; +use std::collections::HashMap; + +use super::*; + +/// Formatting configuration builder. +/// +/// # Example +/// +/// ``` +/// use dprint_plugin_dockerfile::configuration::*; +/// +/// let config = ConfigurationBuilder::new() +/// .line_width(80) +/// .build(); +/// ``` +pub struct ConfigurationBuilder { + pub(super) config: ConfigKeyMap, + global_config: Option, +} + +impl ConfigurationBuilder { + /// Constructs a new configuration builder. + pub fn new() -> ConfigurationBuilder { + ConfigurationBuilder { + config: HashMap::new(), + global_config: None, + } + } + + /// Gets the final configuration that can be used to format a file. + pub fn build(&self) -> Configuration { + if let Some(global_config) = &self.global_config { + resolve_config(self.config.clone(), global_config).config + } else { + let global_config = resolve_global_config(HashMap::new()).config; + resolve_config(self.config.clone(), &global_config).config + } + } + + /// Set the global configuration. + pub fn global_config(&mut self, global_config: GlobalConfiguration) -> &mut Self { + self.global_config = Some(global_config); + self + } + + /// The width of a line the printer will try to stay under. Note that the printer may exceed this width in certain cases. + /// Default: 120 + pub fn line_width(&mut self, value: u32) -> &mut Self { + self.insert("lineWidth", (value as i32).into()) + } + + /// Whether to use tabs (true) or spaces (false). + /// + /// Default: `false` + pub fn use_tabs(&mut self, value: bool) -> &mut Self { + self.insert("useTabs", value.into()) + } + + /// The number of columns for an indent. + /// + /// Default: `2` + pub fn indent_width(&mut self, value: u8) -> &mut Self { + self.insert("indentWidth", (value as i32).into()) + } + + /// The kind of newline to use. + /// Default: `NewLineKind::LineFeed` + pub fn new_line_kind(&mut self, value: NewLineKind) -> &mut Self { + self.insert("newLineKind", value.to_string().into()) + } + + #[cfg(test)] + pub(super) fn get_inner_config(&self) -> ConfigKeyMap { + self.config.clone() + } + + fn insert(&mut self, name: &str, value: ConfigKeyValue) -> &mut Self { + self.config.insert(String::from(name), value); + self + } +} + +#[cfg(test)] +mod tests { + use dprint_core::configuration::{resolve_global_config, NewLineKind}; + use std::collections::HashMap; + + use super::*; + + #[test] + fn check_all_values_set() { + let mut config = ConfigurationBuilder::new(); + config + .new_line_kind(NewLineKind::CarriageReturnLineFeed) + .line_width(90) + .use_tabs(true) + .indent_width(4); + + let inner_config = config.get_inner_config(); + assert_eq!(inner_config.len(), 4); + let diagnostics = resolve_config(inner_config, &resolve_global_config(HashMap::new()).config).diagnostics; + assert_eq!(diagnostics.len(), 0); + } + + #[test] + fn handle_global_config() { + let mut global_config = HashMap::new(); + global_config.insert(String::from("lineWidth"), 90.into()); + global_config.insert(String::from("newLineKind"), "crlf".into()); + global_config.insert(String::from("useTabs"), true.into()); + let global_config = resolve_global_config(global_config).config; + let mut config_builder = ConfigurationBuilder::new(); + let config = config_builder.global_config(global_config).build(); + assert_eq!(config.line_width, 90); + assert_eq!(config.new_line_kind == NewLineKind::CarriageReturnLineFeed, true); + } + + #[test] + fn use_defaults_when_global_not_set() { + let global_config = resolve_global_config(HashMap::new()).config; + let mut config_builder = ConfigurationBuilder::new(); + let config = config_builder.global_config(global_config).build(); + assert_eq!(config.indent_width, 2); // this is different + assert_eq!(config.new_line_kind == NewLineKind::LineFeed, true); + } +} diff --git a/src/configuration/configuration.rs b/src/configuration/configuration.rs new file mode 100644 index 0000000..bbe39fb --- /dev/null +++ b/src/configuration/configuration.rs @@ -0,0 +1,11 @@ +use dprint_core::configuration::NewLineKind; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Configuration { + pub line_width: u32, + pub use_tabs: bool, + pub indent_width: u8, + pub new_line_kind: NewLineKind, +} diff --git a/src/configuration/mod.rs b/src/configuration/mod.rs new file mode 100644 index 0000000..357e324 --- /dev/null +++ b/src/configuration/mod.rs @@ -0,0 +1,7 @@ +mod builder; +mod configuration; +mod resolve_config; + +pub use builder::*; +pub use configuration::*; +pub use resolve_config::*; diff --git a/src/configuration/resolve_config.rs b/src/configuration/resolve_config.rs new file mode 100644 index 0000000..a958622 --- /dev/null +++ b/src/configuration/resolve_config.rs @@ -0,0 +1,58 @@ +use super::Configuration; +use dprint_core::configuration::*; + +/// Resolves configuration from a collection of key value strings. +/// +/// # Example +/// +/// ``` +/// use std::collections::HashMap; +/// use dprint_core::configuration::{resolve_global_config}; +/// use dprint_plugin_dockerfile::configuration::{resolve_config}; +/// +/// let config_map = HashMap::new(); // get a collection of key value pairs from somewhere +/// let global_config_result = resolve_global_config(config_map); +/// +/// // check global_config_result.diagnostics here... +/// +/// let config_map = HashMap::new(); // get a collection of k/v pairs from somewhere +/// let config_result = resolve_config( +/// config_map, +/// &global_config_result.config +/// ); +/// +/// // check config_result.diagnostics here and use config_result.config +/// ``` +pub fn resolve_config(config: ConfigKeyMap, global_config: &GlobalConfiguration) -> ResolveConfigurationResult { + let mut diagnostics = Vec::new(); + let mut config = config; + + let resolved_config = Configuration { + line_width: get_value( + &mut config, + "lineWidth", + global_config.line_width.unwrap_or(DEFAULT_GLOBAL_CONFIGURATION.line_width), + &mut diagnostics, + ), + use_tabs: get_value( + &mut config, + "useTabs", + global_config.use_tabs.unwrap_or(DEFAULT_GLOBAL_CONFIGURATION.use_tabs), + &mut diagnostics, + ), + indent_width: get_value(&mut config, "indentWidth", global_config.indent_width.unwrap_or(2), &mut diagnostics), + new_line_kind: get_value( + &mut config, + "newLineKind", + global_config.new_line_kind.unwrap_or(DEFAULT_GLOBAL_CONFIGURATION.new_line_kind), + &mut diagnostics, + ), + }; + + diagnostics.extend(get_unknown_property_diagnostics(config)); + + ResolveConfigurationResult { + config: resolved_config, + diagnostics, + } +} diff --git a/src/format_text.rs b/src/format_text.rs new file mode 100644 index 0000000..d025161 --- /dev/null +++ b/src/format_text.rs @@ -0,0 +1,9 @@ +use dprint_core::types::ErrBox; +use std::path::Path; + +use crate::configuration::Configuration; + +pub fn format_text(_file_path: &Path, text: &str, _config: &Configuration) -> Result { + // todo :) + Ok(text.to_string()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a86d598 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,15 @@ +pub mod configuration; +mod format_text; + +pub use format_text::format_text; + +#[cfg(feature = "tracing")] +pub use format_text::trace_file; + +#[cfg(feature = "wasm")] +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +mod wasm_plugin; + +#[cfg(feature = "wasm")] +#[cfg(all(target_arch = "wasm32", target_os = "unknown"))] +pub use wasm_plugin::*; diff --git a/src/wasm_plugin.rs b/src/wasm_plugin.rs new file mode 100644 index 0000000..1a77863 --- /dev/null +++ b/src/wasm_plugin.rs @@ -0,0 +1,58 @@ +use dprint_core::configuration::{ConfigKeyMap, GlobalConfiguration, ResolveConfigurationResult}; +use dprint_core::generate_plugin_code; +use dprint_core::plugins::{PluginHandler, PluginInfo}; +use dprint_core::types::ErrBox; +use std::path::Path; + +use super::configuration::{resolve_config, Configuration}; + +struct DockerfilePluginHandler {} + +impl DockerfilePluginHandler { + pub const fn new() -> Self { + DockerfilePluginHandler {} + } +} + +impl PluginHandler for DockerfilePluginHandler { + fn resolve_config(&mut self, config: ConfigKeyMap, global_config: &GlobalConfiguration) -> ResolveConfigurationResult { + resolve_config(config, global_config) + } + + fn get_plugin_info(&mut self) -> PluginInfo { + let version = env!("CARGO_PKG_VERSION").to_string(); + PluginInfo { + name: env!("CARGO_PKG_NAME").to_string(), + version: version.clone(), + config_key: "dockerfile".to_string(), + file_extensions: vec!["dockerfile".to_string()], + file_names: vec![], + help_url: "https://dprint.dev/plugins/dockerfile".to_string(), + config_schema_url: format!("https://plugins.dprint.dev/schemas/dockerfile-{}.json", version), + } + } + + fn get_license_text(&mut self) -> String { + std::str::from_utf8(include_bytes!("../LICENSE")).unwrap().into() + } + + fn format_text( + &mut self, + file_path: &Path, + file_text: &str, + config: &Configuration, + _format_with_host: impl FnMut(&Path, String, &ConfigKeyMap) -> Result, + ) -> Result { + super::format_text(file_path, file_text, config) + } +} + +// for clearing the configuration in the playground +#[no_mangle] +pub fn reset_config() { + unsafe { + RESOLVE_CONFIGURATION_RESULT.get().take(); + } +} + +generate_plugin_code!(DockerfilePluginHandler, DockerfilePluginHandler::new());