Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Remove Newlines" filter #47

Merged
merged 5 commits into from
May 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ Due to the removal of legacy code, there are a few breaking changes in this new

### New Features

_None_
* Added the `removeNewlines` filter to remove newlines (and spaces) from a string.
[David Jennes](https://github.com/djbe)
[#47](https://github.com/SwiftGen/StencilSwiftKit/pull/47)

### Internal Changes

Expand Down
126 changes: 73 additions & 53 deletions Documentation/filters-strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,38 @@

This is a list of filters that are added by StencilSwiftKit on top of the filters already provided by Stencil (which you can [find here](http://stencil.fuller.li/en/latest/builtins.html#built-in-filters)).

## Filter: `camelToSnakeCase`

Transforms text from camelCase to snake_case.

| Input | Output |
|-------------------------|-------------------------|
| `SomeCapString` | `some_cap_string` |
| `string_with_words` | `string_with_words` |
| `STRing_with_words` | `st_ring_with_words` |
| `URLChooser` | `url_chooser` |
| `PLEASE_STOP_SCREAMING` | `please_stop_screaming` |

By default it converts to lower case, unless a single optional argument is set to "false", "no" or "0":

| Input | Output |
|--------------------------|--------------------------|
| `SomeCapString` | `Some_Cap_String` |
| `someCapString` | `some_Cap_String` |
| `String_With_WoRds` | `String_With_Wo_Rds` |
| `string_wiTH_WOrds` | `string_wi_TH_W_Ords` |
| `URLChooser` | `URL_Chooser` |
| `PLEASE_STOP_SCREAMING!` | `PLEASE_STOP_SCREAMING!` |

## Filter: `escapeReservedKeywords`

Checks if the given string matches a reserved Swift keyword. If it does, wrap the string in escape characters (backticks).

| Input | Output |
|-------|---------------------------------|
| hello | hello |
| self | \`self\` |
| Any | \`Any\` |
| Input | Output |
|---------|--------------|
| `hello` | `hello` |
| `self` | `` `self` `` |
| `Any` | `` `Any` `` |

## Filter: `lowerFirstWord`

Expand All @@ -19,10 +42,30 @@ Transforms an arbitrary string so that only the first "word" is lowercased.
- If the string starts with only one uppercase character, lowercase that first character.
- If the string starts with multiple uppercase character, lowercase those first characters up to the one before the last uppercase one, but only if the last one is followed by a lowercase character. This allows to support strings beginnng with an acronym, like `URL`.

| Input | Output |
|--------------|--------------------------|
| PeoplePicker | peoplePicker |
| URLChooser | urlChooser |
| Input | Output |
|----------------|--------------------------|
| `PeoplePicker` | `peoplePicker` |
| `URLChooser` | `urlChooser` |

## Filter: `removeNewlines`

Removes all newlines and whitespace characters from the string.

| Input | Output |
|-----------------------|-----------------------|
| ` \ntest` | `test` |
| `test \n\t ` | `test` |
| `test\n test` | `testtest` |
| `\r\ntest\n test\n` | `testtest` |

By default it removes whitespace characters, unless a single optional argument is set to "false", "no" or "0":

| Input | Output |
|-----------------------|-----------------------|
| ` \ntest` | ` test` |
| `test \n\t ` | `test \t ` |
| `test\n test` | `test test` |
| `\r\ntest\n test\n` | `test test` |

## Filter: `snakeToCamelCase`

Expand All @@ -34,44 +77,21 @@ Transforms a string in "snake_case" format into one in "camelCase" format, follo

If the whole starting "snake_case" string only contained uppercase characters, then each component will be capitalized: uppercase the first character and lowercase the other characters.

| Input | Output |
|--------------|--------------------------|
| snake_case | SnakeCase |
| snAke_case | SnAkeCase |
| SNAKE_CASE | SnakeCase |
| __snake_case | __SnakeCase |
| Input | Output |
|----------------|---------------|
| `snake_case` | `SnakeCase` |
| `snAke_case` | `SnAkeCase` |
| `SNAKE_CASE` | `SnakeCase` |
| `__snake_case` | `__SnakeCase` |

This filter accepts a parameter (boolean, default `false`) that controls the prefixing behaviour. If set to `true`, it will trim empty components from the beginning of the string

| Input | Output |
|--------------|--------------------------|
| snake_case | SnakeCase |
| snAke_case | SnAkeCase |
| SNAKE_CASE | SnakeCase |
| __snake_case | SnakeCase |

## Filter: `camelToSnakeCase`

Transforms text from camelCase to snake_case.

| Input | Output |
|-----------------------|-----------------------|
| SomeCapString | some_cap_string |
| string_with_words | string_with_words |
| STRing_with_words | st_ring_with_words |
| URLChooser | url_chooser |
| PLEASE_STOP_SCREAMING | please_stop_screaming |

By default it converts to lower case, unless a single optional argument is set to "false", "no" or "0":

| Input | Output |
|------------------------|--------------------------|
| SomeCapString | Some_Cap_String |
| someCapString | some_Cap_String |
| String_With_WoRds | String_With_Wo_Rds |
| string_wiTH_WOrds | string_wi_TH_W_Ords |
| URLChooser | URL_Chooser |
| PLEASE_STOP_SCREAMING! | PLEASE_STOP_SCREAMING! |
| Input | Output |
|----------------|-------------|
| `snake_case` | `SnakeCase` |
| `snAke_case` | `SnAkeCase` |
| `SNAKE_CASE` | `SnakeCase` |
| `__snake_case` | `SnakeCase` |

## Filter: `swiftIdentifier`

Expand All @@ -84,19 +104,19 @@ Transforms an arbitrary string into a valid Swift identifier (using only valid c
The list of allowed characters can be found here:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html

| Input | Output |
|----------|------------------------------|
| hello | Hello |
| 42hello | _42hello |
| some$URL | Some_URL |
| Input | Output |
|------------|------------|
| `hello` | `Hello` |
| `42hello` | `_42hello` |
| `some$URL` | `Some_URL` |

## Filter: `titlecase`

Simply uppercases the first character, leaving the other characters untouched.

Note that even if very similar, this filter differs from the `capitalized` filter, which uppercases the first character but also lowercases the remaining characters.

| Input | Output |
|---------------|-------------------------|
| hello | Hello |
| peopleChooser | PeopleChooser |
| Input | Output |
|-----------------|-----------------|
| `hello` | `Hello` |
| `peopleChooser` | `PeopleChooser` |
9 changes: 6 additions & 3 deletions Sources/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ public extension Extension {
registerTag("macro", parser: MacroNode.parse)
registerTag("call", parser: CallNode.parse)
registerTag("map", parser: MapNode.parse)
registerFilter("swiftIdentifier", filter: Filters.Strings.swiftIdentifier)

registerFilter("camelToSnakeCase", filter: Filters.Strings.camelToSnakeCase)
registerFilter("escapeReservedKeywords", filter: Filters.Strings.escapeReservedKeywords)
registerFilter("lowerFirstWord", filter: Filters.Strings.lowerFirstWord)
registerFilter("removeNewlines", filter: Filters.Strings.removeNewlines)
registerFilter("snakeToCamelCase", filter: Filters.Strings.snakeToCamelCase)
registerFilter("camelToSnakeCase", filter: Filters.Strings.camelToSnakeCase)
registerFilter("swiftIdentifier", filter: Filters.Strings.swiftIdentifier)
registerFilter("titlecase", filter: Filters.Strings.titlecase)

registerFilter("hexToInt", filter: Filters.Numbers.hexToInt)
registerFilter("int255toFloat", filter: Filters.Numbers.int255toFloat)
registerFilter("percent", filter: Filters.Numbers.percent)
registerFilter("escapeReservedKeywords", filter: Filters.Strings.escapeReservedKeywords)
}
}

Expand Down
10 changes: 10 additions & 0 deletions Sources/Filters+Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ extension Filters {
return escapeReservedKeywords(in: string)
}

static func removeNewlines(_ value: Any?, arguments: [Any?]) throws -> Any? {
let removeSpaces = try Filters.parseBool(from: arguments, index: 0, required: false) ?? true
guard let string = value as? String else { throw Filters.Error.invalidInputType }

let set: CharacterSet = removeSpaces ? .whitespacesAndNewlines : .newlines
let result = string.components(separatedBy: set).joined()

return result
}

// MARK: - Private methods

/// This returns the string with its first parameter uppercased.
Expand Down
34 changes: 17 additions & 17 deletions Sources/MapNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class MapNode: NodeType {

if let values = values as? [Any], values.count > 0 {
let mappedValues: [String] = try values.enumerated().map { (index, item) in
let mapContext = self.context(values: values, index: index, item: item)
let mapContext = self.context(values: values, index: index, item: item)

return try context.push(dictionary: mapContext) {
try renderNodes(nodes, context)
Expand All @@ -68,20 +68,20 @@ class MapNode: NodeType {
return ""
}

func context(values: [Any], index: Int, item: Any) -> [String: Any] {
var result: [String: Any] = [
"maploop": [
"counter": index,
"first": index == 0,
"last": index == (values.count - 1),
"item": item
]
]

if let mapVariable = mapVariable {
result[mapVariable] = item
}

return result
}
func context(values: [Any], index: Int, item: Any) -> [String: Any] {
var result: [String: Any] = [
"maploop": [
"counter": index,
"first": index == 0,
"last": index == (values.count - 1),
"item": item
]
]

if let mapVariable = mapVariable {
result[mapVariable] = item
}

return result
}
}
Loading